• Springboot利用Security做OAuth2授权验证


    OAuth2获取授权令牌(token)通常有四种方式:授权码模式,简化模式,客户端模式,和密码模式。针对自己系统内用户的登录,通常使用密码模式进行授权。

    我们利用Spring Security OAuth2来制作一个授权服务器。

    第一步 添加依赖

    pom文件中添加如下依赖,引入oauth2相关框架

    1. <dependency>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-webartifactId>
    4. dependency>
    5. <dependency>
    6. <groupId>org.springframework.cloudgroupId>
    7. <artifactId>spring-cloud-starter-securityartifactId>
    8. dependency>
    9. <dependency>
    10. <groupId>org.springframework.cloudgroupId>
    11. <artifactId>spring-cloud-starter-oauth2artifactId>
    12. dependency>

    我还是用到了数据库进行存储,我用的jpa连接数据库,使用其他持久层框架(MyBatis)也可以。

    引入数据库依赖

    1. <dependency>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-data-jpaartifactId>
    4. dependency>
    5. <dependency>
    6. <groupId>mysqlgroupId>
    7. <artifactId>mysql-connector-javaartifactId>
    8. dependency>

    第二步 添加代码

    1 实现UserDetailsService,获取用户

    1. @Service
    2. public class MyUserDetailsService implements UserDetailsService {
    3. @Resource
    4. private UserService userService;
    5. @Override
    6. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    7. //根据用户名获取用户,并验证用户是否有效及权限
    8. //从数据库中获取用户
    9. TUser user = userService.findByUsername(username);
    10. if (user == null) {
    11. throw new UsernameNotFoundException("用户不存在");
    12. }
    13. Set grantedAuthorities = new HashSet<>();
    14. boolean enabled = user.getStatus() == 1; // 可用性 :true:可用 false:不可用
    15. boolean accountNonExpired = true; // 过期性 :true:没过期 false:过期
    16. boolean credentialsNonExpired = true; // 有效性 :true:凭证有效 false:凭证无效
    17. boolean accountNonLocked = true; // 锁定性 :true:未锁定 false:已锁定
    18. //配置权限
    19. GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ADMIN");
    20. grantedAuthorities.add(grantedAuthority);
    21. //将用户名和密码及其他配置返还个spring security 进行验证
    22. return new User(username, user.getPassword(),
    23. enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, grantedAuthorities);
    24. }
    25. }

    2 添加WebSecurityConfigurerAdapter

    1. @Configuration
    2. @EnableWebSecurity
    3. public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    4. @Bean
    5. public PasswordEncoder passwordEncoder() {
    6. return new BCryptPasswordEncoder();
    7. }
    8. @Override
    9. @Bean
    10. public AuthenticationManager authenticationManagerBean() throws Exception {
    11. return super.authenticationManagerBean();
    12. }
    13. }

    3 添加AuthorizationServerConfigurerAdapter

    1. @Configuration
    2. @EnableAuthorizationServer
    3. public class Oauth2ServerConfig extends AuthorizationServerConfigurerAdapter {
    4. //验证管理器
    5. @Resource
    6. private AuthenticationManager authenticationManager;
    7. //获取用户,自己实现获取用户的相关功能
    8. @Resource
    9. private MyUserDetailsService userService;
    10. //数据库配置
    11. @Resource
    12. private DataSource dataSource;
    13. /**
    14. * 自定义授权服务配置
    15. */
    16. @Override
    17. public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
    18. endpoints.authenticationManager(authenticationManager)
    19. .userDetailsService(userService)
    20. .tokenStore(new JdbcTokenStore(dataSource));
    21. // 配置TokenServices参数
    22. DefaultTokenServices tokenServices = new DefaultTokenServices();
    23. tokenServices.setTokenStore(endpoints.getTokenStore());
    24. tokenServices.setSupportRefreshToken(true);
    25. tokenServices.setClientDetailsService(endpoints.getClientDetailsService());
    26. tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
    27. tokenServices.setAccessTokenValiditySeconds((int) TimeUnit.HOURS.toSeconds(12)); // 12小时
    28. tokenServices.setRefreshTokenValiditySeconds((int) TimeUnit.DAYS.toSeconds(30));// 30天
    29. endpoints.tokenServices(tokenServices);
    30. }
    31. /**
    32. * 配置认证客户端
    33. * @param clients
    34. * @throws Exception
    35. */
    36. @Override
    37. public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    38. //自定义客户端配置
    39. clients.withClientDetails(clientDetails());
    40. }
    41. //从数据库中获取客户端的配置
    42. public ClientDetailsService clientDetails() {
    43. return new JdbcClientDetailsService(dataSource);
    44. }
    45. /**
    46. * 自定义授权令牌端点的安全约束
    47. * @param security
    48. */
    49. @Override
    50. public void configure(AuthorizationServerSecurityConfigurer security) {
    51. //自定义安全约束
    52. security.allowFormAuthenticationForClients();
    53. }
    54. }

    第三步 初始化数据库

    在数据库中创建三个表 oauth_access_token (存储token),oauth_client_details(允许请求授权的客户端),oauth_refresh_token(存储refreshToken)

    为了测试,我还建了一个t_user的用户表,这个表可以不导入

    1. CREATE TABLE `oauth_access_token` (
    2. `token_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
    3. `token` blob NULL,
    4. `authentication_id` varchar(250) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
    5. `user_name` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
    6. `client_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
    7. `authentication` blob NULL,
    8. `refresh_token` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
    9. PRIMARY KEY (`authentication_id`) USING BTREE
    10. ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
    11. CREATE TABLE `oauth_client_details` (
    12. `client_id` varchar(250) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
    13. `resource_ids` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
    14. `client_secret` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
    15. `scope` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
    16. `authorized_grant_types` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
    17. `web_server_redirect_uri` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
    18. `authorities` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
    19. `access_token_validity` int(11) NULL DEFAULT NULL,
    20. `refresh_token_validity` int(11) NULL DEFAULT NULL,
    21. `additional_information` varchar(4096) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
    22. `autoapprove` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
    23. PRIMARY KEY (`client_id`) USING BTREE
    24. ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
    25. -- 初始化了一个客户端的数据
    26. INSERT INTO `oauth_client_details` VALUES ('client', '', '$2a$10$My8G.sWJs/WQN8hdYS862.BsUuoL4p51xyfTIJu2NMMrIQ/JXRc2a', 'web', 'authorization_code,password,refresh_token,client_credentials', NULL, NULL, NULL, NULL, '{\"code\":\"test\"}', NULL);
    27. DROP TABLE IF EXISTS `oauth_refresh_token`;
    28. CREATE TABLE `oauth_refresh_token` (
    29. `token_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
    30. `token` blob NULL,
    31. `authentication` blob NULL
    32. ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
    33. -- 我自己测试用的用户表,这个可以不导入,使用自己系统的用户表
    34. DROP TABLE IF EXISTS `t_user`;
    35. CREATE TABLE `t_user` (
    36. `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
    37. `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',
    38. `nickname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '昵称',
    39. `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',
    40. `status` int(11) NULL DEFAULT NULL COMMENT '状态 1正常 2停用',
    41. `e_mail` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '电子邮箱',
    42. `phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '手机号',
    43. PRIMARY KEY (`id`) USING BTREE
    44. ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    45. INSERT INTO `t_user` VALUES (1, 'admin', '管理员', '$2a$10$gD1u5uXEmCFmlvg.hgN7P.zv.sbCOEmX1sFNRHEBRIx6Ad.qydceu', 1, 'admin@admin.com', '15812345678');

    在application中配置数据库信息

    1. spring:
    2. application:
    3. name: HelloSecurity
    4. #数据库配置连接
    5. datasource:
    6. url: jdbc:mysql://127.0.0.1:3306/hello_security?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    7. username: root
    8. password: "123456"
    9. driver-class-name: com.mysql.cj.jdbc.Driver
    10. jpa:
    11. show-sql: true
    12. server:
    13. port: 8080

    完成以上步骤后,一个简单的OAuth2授权验证服务器就搭建完成了,我们启动项目,进行测试。

    获取token的接口是 http://127.0.0.1:8080/oauth/token

     源码地址:https://gitee.com/xiaobailovejiajia/hello-security

  • 相关阅读:
    动态代理jdk和cglib
    【面试必刷TOP101】链表相加 & 单链表的排序
    【直播笔记0629】 并发编程二:锁
    postgresql之integerset
    java-net-php-python-springtboot校园信息交流互助系统计算机毕业设计程序
    Windows 安装DotNet Core运行时库
    锁的优化机制了解吗?
    机械硬盘,Win10系统,磁盘100%
    Spine2D骨骼动画播放器 - 微信小程序版
    计算二进制中1的个数
  • 原文地址:https://blog.csdn.net/dengdaijc/article/details/128168388