Springboot使用Security实现OAuth2授权验证完整过程

 更新时间:2022年12月12日 10:57:52   作者:LO嘉嘉VE  
安全管理是软件系统必不可少的的功能。根据经典的“墨菲定律”——凡是可能,总会发生。如果系统存在安全隐患,最终必然会出现问题,这篇文章主要介绍了SpringBoot使用Security实现OAuth2授权验证完整过程

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

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

第一步-添加依赖

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>

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

引入数据库依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!--数据库链接驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

第二步-添加代码

1 实现UserDetailsService,获取用户

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

2 添加WebSecurityConfigurerAdapter

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

3 添加AuthorizationServerConfigurerAdapter

@Configuration
@EnableAuthorizationServer
public class Oauth2ServerConfig extends AuthorizationServerConfigurerAdapter {
    //验证管理器
    @Resource
    private AuthenticationManager authenticationManager;
    //获取用户,自己实现获取用户的相关功能
    @Resource
    private MyUserDetailsService userService;
    //数据库配置
    @Resource
    private DataSource dataSource;
    /**
     * 自定义授权服务配置
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints.authenticationManager(authenticationManager)
                .userDetailsService(userService)
                .tokenStore(new JdbcTokenStore(dataSource));
        // 配置TokenServices参数
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setTokenStore(endpoints.getTokenStore());
        tokenServices.setSupportRefreshToken(true);
        tokenServices.setClientDetailsService(endpoints.getClientDetailsService());
        tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
        tokenServices.setAccessTokenValiditySeconds((int) TimeUnit.HOURS.toSeconds(12)); // 12小时
        tokenServices.setRefreshTokenValiditySeconds((int) TimeUnit.DAYS.toSeconds(30));// 30天
        endpoints.tokenServices(tokenServices);
    }
    /**
     * 配置认证客户端
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        //自定义客户端配置
        clients.withClientDetails(clientDetails());
    }
    //从数据库中获取客户端的配置
    public ClientDetailsService clientDetails() {
        return new JdbcClientDetailsService(dataSource);
    }
    /**
     * 自定义授权令牌端点的安全约束
     * @param security
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) {
        //自定义安全约束
        security.allowFormAuthenticationForClients();
    }
}

第三步-初始化数据库

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

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

CREATE TABLE `oauth_access_token`  (
  `token_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `token` blob NULL,
  `authentication_id` varchar(250) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `user_name` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `client_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `authentication` blob NULL,
  `refresh_token` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`authentication_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
CREATE TABLE `oauth_client_details`  (
  `client_id` varchar(250) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `resource_ids` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `client_secret` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `scope` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `authorized_grant_types` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `web_server_redirect_uri` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `authorities` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `access_token_validity` int(11) NULL DEFAULT NULL,
  `refresh_token_validity` int(11) NULL DEFAULT NULL,
  `additional_information` varchar(4096) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `autoapprove` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`client_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
-- 初始化了一个客户端的数据
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);
DROP TABLE IF EXISTS `oauth_refresh_token`;
CREATE TABLE `oauth_refresh_token`  (
  `token_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `token` blob NULL,
  `authentication` blob NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
-- 我自己测试用的用户表,这个可以不导入,使用自己系统的用户表
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',
  `nickname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '昵称',
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',
  `status` int(11) NULL DEFAULT NULL COMMENT '状态 1正常 2停用',
  `e_mail` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '电子邮箱',
  `phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '手机号',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `t_user` VALUES (1, 'admin', '管理员', '$2a$10$gD1u5uXEmCFmlvg.hgN7P.zv.sbCOEmX1sFNRHEBRIx6Ad.qydceu', 1, 'admin@admin.com', '15812345678');

在application中配置数据库信息

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

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

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

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

到此这篇关于Springboot使用Security实现OAuth2授权验证完整过程的文章就介绍到这了,更多相关Springboot Security内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 让你五分钟彻底理解Spring MVC

    让你五分钟彻底理解Spring MVC

    其实MVC就是处理Web请求的一种框架模式,如果你对MVC不太熟悉的话可以看下本文,这篇文章主要给大家介绍了关于如何让你五分钟彻底理解Spring MVC的相关资料,需要的朋友可以参考下
    2021-10-10
  • 详解Java的TCP/IP编程学习--基于定界符的成帧

    详解Java的TCP/IP编程学习--基于定界符的成帧

    这篇文章主要介绍了Java的TCP/IP编程学习--基于定界符的成帧,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • Java实现简单修改文件名的方法分析

    Java实现简单修改文件名的方法分析

    这篇文章主要介绍了Java实现简单修改文件名的方法,结合具体实例分析了2种比较常用的java文件名修改方法,需要的朋友可以参考下
    2017-09-09
  • SpringMVC中的HandlerMapping详解

    SpringMVC中的HandlerMapping详解

    这篇文章主要介绍了SpringMVC中的HandlerMapping详解,HandlerMapping是请求映射处理器,也就是通过请求的url找到对应的逻辑处理单元(Controller),注意这里只是建立请求与Controller的映射关系,最终的处理是通过HandlerAdapt来进行处理的,需要的朋友可以参考下
    2023-09-09
  • Java异常:java.net.UnknownHostException产生的原因和解决方案

    Java异常:java.net.UnknownHostException产生的原因和解决方案

    这篇文章主要给大家介绍了关于Java异常:java.net.UnknownHostException产生的原因和解决方案,这个异常是java.net包中的一部分,具体说它是类的一个实例,异常通常是由主机名无法解析为IP地址引起的,文中将解决的办法介绍的非常详细,需要的朋友可以参考下
    2024-01-01
  • SpringBoot中@Import注解如何正确使用

    SpringBoot中@Import注解如何正确使用

    这篇文章主要介绍了SpringBoot中@Import注解的使用方式,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-06-06
  • Spring加载XSD文件发生错误的解决方法

    Spring加载XSD文件发生错误的解决方法

    这篇文章主要介绍了Spring加载XSD文件发生错误的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-08-08
  • 浅谈Spring5 响应式编程

    浅谈Spring5 响应式编程

    本篇文章主要介绍了浅谈Spring5 响应式编程,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • 解决springboot整合druid遇到的坑

    解决springboot整合druid遇到的坑

    这篇文章主要介绍了解决springboot整合druid遇到的坑,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • Collections工具类_动力节点Java学院整理

    Collections工具类_动力节点Java学院整理

    Collections工具类提供了大量针对Collection/Map的操作。这篇文章主要介绍了Collections工具类_动力节点Java学院整理,需要的朋友可以参考下
    2017-04-04

最新评论