写在前边

本文对Spring Security OAuth2的token使用Redis保存,相比JWT实现的token存储,Redis可以随时吊销access_token,并且Redis响应速度很快,没有加密解密的过程

本文源代码在redis-token-saved模块中,仓库地址:https://github.com/hellxz/spring-security-oauth2-learn

这里就不做测试了,仅做简记

代码层级

Maven依赖

  1. <parent>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-parent</artifactId>
  4. <version>2.2.1.RELEASE</version>
  5. <relativePath/> <!-- lookup parent from repository -->
  6. </parent>
  7. <dependencies>
  8. <!-- Spring Security OAuth2 -->
  9. <dependency>
  10. <groupId>org.springframework.security.oauth</groupId>
  11. <artifactId>spring-security-oauth2</artifactId>
  12. <version>2.4.0.RELEASE</version>
  13. </dependency>
  14. <dependency>
  15. <groupId>org.springframework.boot</groupId>
  16. <artifactId>spring-boot-starter-data-redis</artifactId>
  17. </dependency>
  18. <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
  19. <dependency>
  20. <groupId>com.alibaba</groupId>
  21. <artifactId>fastjson</artifactId>
  22. <version>1.2.62</version>
  23. </dependency>
  24. </dependencies>

授权服务器保存token到Redis

application.yml

  1. server:
  2. port: 8080
  3. spring:
  4. redis:
  5. host: 127.0.0.1
  6. port: 6379
  7. password: 123
  8. database: 0

AuthorizationConfig

  1. @Configuration
  2. @EnableAuthorizationServer
  3. public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
  4. /**
  5. * redis工厂,默认使用lettue
  6. */
  7. @Autowired
  8. public RedisConnectionFactory redisConnectionFactory;
  9. /**
  10. * 用户认证管理器
  11. */
  12. @Autowired
  13. public AuthenticationManager authenticationManager;
  14. /**
  15. * 用户服务
  16. */
  17. @Autowired
  18. public UserDetailsService userDetailsService;
  19. /**
  20. * 密码加密器
  21. */
  22. @Autowired
  23. private PasswordEncoder passwordEncoder;
  24. /**
  25. * 授权服务安全配置,主要用于放行客户端访问授权服务接口
  26. *
  27. * @param security AuthorizationServerSecurityConfigurer
  28. * @throws Exception 异常
  29. */
  30. @Override
  31. public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
  32. //允许客户端表单提交
  33. security.allowFormAuthenticationForClients()
  34. //客户端校验token访问许可
  35. .checkTokenAccess("permitAll()")
  36. //客户端token调用许可
  37. .tokenKeyAccess("permitAll()");
  38. }
  39. /**
  40. * 客户端信息配置,可配置多个客户端,这里可以使用配置文件进行代替
  41. *
  42. * @param clients 客户端设置
  43. * @throws Exception 异常
  44. */
  45. @Override
  46. public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
  47. clients.inMemory()
  48. .withClient("client-a")
  49. .secret(passwordEncoder.encode("client-a-secret"))
  50. .redirectUris("http://localhost:9001/callback")
  51. //支持 授权码、密码两种授权模式,支持刷新token功能
  52. .authorizedGrantTypes("authorization_code", "password", "refresh_token");
  53. }
  54. /**
  55. * 配置端点
  56. *
  57. * @param endpoints 端点
  58. * @throws Exception 异常
  59. */
  60. @Override
  61. public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
  62. //配置认证管理器
  63. endpoints.authenticationManager(authenticationManager)
  64. //配置用户服务
  65. .userDetailsService(userDetailsService)
  66. //配置token存储的服务与位置
  67. .tokenServices(tokenService())
  68. .tokenStore(tokenStore());
  69. }
  70. @Bean
  71. public TokenStore tokenStore() {
  72. //使用redis存储token
  73. RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
  74. //设置redis token存储中的前缀
  75. redisTokenStore.setPrefix("auth-token:");
  76. return redisTokenStore;
  77. }
  78. @Bean
  79. public DefaultTokenServices tokenService() {
  80. DefaultTokenServices tokenServices = new DefaultTokenServices();
  81. //配置token存储
  82. tokenServices.setTokenStore(tokenStore());
  83. //开启支持refresh_token,此处如果之前没有配置,启动服务后再配置重启服务,可能会导致不返回token的问题,解决方式:清除redis对应token存储
  84. tokenServices.setSupportRefreshToken(true);
  85. //复用refresh_token
  86. tokenServices.setReuseRefreshToken(true);
  87. //token有效期,设置12小时
  88. tokenServices.setAccessTokenValiditySeconds(12 * 60 * 60);
  89. //refresh_token有效期,设置一周
  90. tokenServices.setRefreshTokenValiditySeconds(7 * 24 * 60 * 60);
  91. return tokenServices;
  92. }
  93. }

SecurityConfig

  1. @Configuration
  2. @EnableWebSecurity
  3. public class SecurityConfig extends WebSecurityConfigurerAdapter {
  4. @Bean
  5. public PasswordEncoder passwordEncoder() {
  6. return new BCryptPasswordEncoder();
  7. }
  8. /**
  9. * 配置认证管理器信息,这里可以使用UserDetailsService实现类来提供用户信息,或Provider+UserDetailsService
  10. *
  11. * @param auth 认证管理器配置
  12. * @throws Exception 异常
  13. */
  14. @Override
  15. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  16. //@formatter:off
  17. auth.inMemoryAuthentication()
  18. .withUser("hellxz")
  19. .password(passwordEncoder().encode("test"))
  20. .authorities(AuthorityUtils.createAuthorityList("all"));
  21. //@formatter:on
  22. }
  23. /**
  24. * 配置http访问控制
  25. *
  26. * @param http http安全配置
  27. * @throws Exception 异常
  28. */
  29. @Override
  30. protected void configure(HttpSecurity http) throws Exception {
  31. http.authorizeRequests()
  32. //放行options方法请求
  33. .antMatchers(HttpMethod.OPTIONS).permitAll()
  34. .anyRequest().authenticated()
  35. .and()
  36. .csrf().disable();
  37. }
  38. @Bean
  39. public AuthenticationManager authenticationManager() throws Exception {
  40. return super.authenticationManager();
  41. }
  42. @Bean
  43. public UserDetailsService userDetailsService() {
  44. return super.userDetailsService();
  45. }
  46. }

启动类

  1. /**
  2. * redis作为token存储的授权server
  3. */
  4. @SpringBootApplication
  5. public class RedisAuthorizationServer {
  6. public static void main(String[] args) {
  7. SpringApplication.run(RedisAuthorizationServer.class, args);
  8. }
  9. }

资源服务器访问Redis校验token配置

application.yml

  1. server:
  2. port: 8081
  3. spring:
  4. redis:
  5. host: 127.0.0.1
  6. port: 6379
  7. password: 123
  8. database: 0

ResourceServerConfig

  1. @Configuration
  2. @EnableResourceServer
  3. public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
  4. @Autowired
  5. private RedisConnectionFactory redisConnectionFactory;
  6. @Override
  7. public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
  8. //无状态
  9. resources.stateless(true);
  10. //设置token存储
  11. resources.tokenStore(tokenStore());
  12. }
  13. /**
  14. * 设置token存储,这一点配置要与授权服务器相一致
  15. */
  16. @Bean
  17. public RedisTokenStore tokenStore(){
  18. RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
  19. redisTokenStore.setPrefix("auth-token:");
  20. return redisTokenStore;
  21. }
  22. }

SecurityConfig

  1. @Configuration
  2. @EnableWebSecurity
  3. public class SecurityConfig extends WebSecurityConfigurerAdapter {
  4. @Override
  5. protected void configure(HttpSecurity http) throws Exception {
  6. http.csrf().disable()
  7. .authorizeRequests()
  8. .anyRequest().authenticated()
  9. .and()
  10. .httpBasic();
  11. }
  12. }

ResourceController

  1. @RestController
  2. public class ResourceController {
  3. private static final Logger log = LoggerFactory.getLogger(ResourceController.class);
  4. @GetMapping("/user/{username}")
  5. public UserVO user(@PathVariable String username){
  6. log.info("{}", SecurityContextHolder.getContext().getAuthentication());
  7. return new UserVO(username, username + "@foxmail.com");
  8. }
  9. }

UserVO

  1. package com.github.hellxz.oauth2.web.vo;
  2. public class UserVO {
  3. private String username;
  4. private String email;
  5. public UserVO(String username, String email) {
  6. this.username = username;
  7. this.email = email;
  8. }
  9. public String getUsername() {
  10. return username;
  11. }
  12. public void setUsername(String username) {
  13. this.username = username;
  14. }
  15. public String getEmail() {
  16. return email;
  17. }
  18. public void setEmail(String email) {
  19. this.email = email;
  20. }
  21. }

启动类

  1. /**
  2. * 使用redis作为token存储的资源服务器,这里不使用调用授权服务器的方式去校验资源,只需要从redis中取token进行判断即可
  3. */
  4. @SpringBootApplication
  5. public class RedisResourceServer {
  6. public static void main(String[] args) {
  7. SpringApplication.run(RedisResourceServer.class, args);
  8. }
  9. }

使用Redis作为Spring Security OAuth2的token存储的更多相关文章

  1. 使用JWT作为Spring Security OAuth2的token存储

    序 Spring Security OAuth2的demo在前几篇文章中已经讲过了,在那些模式中使用的都是RemoteTokenService调用授权服务器来校验token,返回校验通过的用户信息供上 ...

  2. Spring Security Oauth2 使用 token 访问资源服务器出现异常:Invalid token does not contain resource id (oauth2)

    异常如图 查看资源服务器的日志 p.a.OAuth2AuthenticationProcessingFilter : Authentication request failed: error=&quo ...

  3. Spring Security OAuth2 微服务认证中心自定义授权模式扩展以及常见登录认证场景下的应用实战

    一. 前言 [APP 移动端]Spring Security OAuth2 手机短信验证码模式 [微信小程序]Spring Security OAuth2 微信授权模式 [管理系统]Spring Se ...

  4. spring security oauth2 搭建认证中心demo

    oauth2 介绍 ​ oauth2 协议应该是开发者们耳熟能详的协议了,这里就不做过多的介绍了,具体介绍如何在spring security中搭建oauth2的认证服务.Spring-Securit ...

  5. spring security oauth2 client_credentials模

    spring security oauth2 client_credentials模 https://www.jianshu.com/p/1c3eea71410e 序 本文主要简单介绍一下spring ...

  6. Spring security + oauth2.0 + redis + mybatis plus 搭建微服务

    上个星期一个朋友请求帮忙,让我搭建一个分布式授权中心的微服务,之前我也没搭建过,在网上撸了几天前辈们写的技术博客,搞出个模型,分享给大家: 前辈们博客地址: OAuth2.0 原理:https://b ...

  7. spring security oauth2搭建resource-server demo及token改造成JWT令牌

    我们在上文讲了如何在spring security的环境中搭建基于oauth2协议的认证中心demo:https://www.cnblogs.com/process-h/p/15688971.html ...

  8. 关于 Spring Security OAuth2 中 Feign 调用 Token 问题

    微服务体系中,避免不了服务之间链式调用,一般使用 Feign ,由于使用 Spring Security OAuth2 全局做了安全认证,简单的一种实现方式就是在服务提供方获得 Token 再次通过 ...

  9. Spring Security Oauth2 的配置

    使用oauth2保护你的应用,可以分为简易的分为三个步骤 配置资源服务器 配置认证服务器 配置spring security 前两点是oauth2的主体内容,但前面我已经描述过了,spring sec ...

随机推荐

  1. Linux - 几种方法来实现scp拷贝时无需输入密码

    前言 在实际工作中,经常会将本地的一些文件传送到远程的机器上.scp是一个很好用的命令,缺点是需要手工输入密码. 如何在shell脚本中实现传输文件,而不用手工输入密码呢?接下来介绍三种方法. 一.建 ...

  2. 码云git常用命令

    Git常用操作命令: 1) 远程仓库相关命令 检出仓库:$ git clone git://github.com/jquery/jquery.git 查看远程仓库:$ git remote -v 添加 ...

  3. XSS攻击(跨站脚本攻击)

    一.什么是XSS?怎么发生的? XSS(Cross site scripting)全称为跨站脚本攻击,是web程序中最常见的漏洞.指攻击者在网页中嵌入客户端脚本(例如Javascript),当用户浏览 ...

  4. JS基础语法---break关键字

    break关键字: 如果在循环中使用,遇到了break,则立刻跳出当前所在的循环       for (var i = 0; i < 10; i++) {         while (true ...

  5. windows宿主机和docker容器设置挂载共享文件夹

    docker容器内的程序经常需要访问.调用宿主机目录中的数据,每次都要导入导出非常麻烦费力. 接下来,一步步实现将宿主机的指定文件夹挂载到docker容器中. 1. 打开Oracle VM Vitua ...

  6. 【BZOJ1443】[JSOI2009]游戏Game(二分图+博弈)

    BZOJ 题意: 给出一个\(n*m\)的网格,其中有一些障碍点. 现在两个人玩游戏,首先先手选定一个点,然后从后手开始轮流移动,不能移动者即输掉这次游戏. 规定不能移动到那些之前已经到过的格子上. ...

  7. 第十五周博客作业 <西北师范大学| 周安伟>

    第十五周作业 助教博客链接https://home.cnblogs.com/u/zaw-315/ 作业要求链接https://www.cnblogs.com/nwnu-daizh/p/10946673 ...

  8. 通过Python代码操作MySQL:

    pymsql / MySQLdb pymysql支持 py2/py3 MySQLdb支持py2 ORM框架 django orm ( 自己对数据连接有优化机制 ) SQLAlchemy ( 自带数据库 ...

  9. IntelliJ IDEA常用配置(三)

    提示:对于一些通用的设置可以配置成全局的. 1. 主题配置 File - Settings - Color Scheme,默认的是Default(一个白色主题),Darcula是一个黑色主题. 我们也 ...

  10. 剑指Offer-6.旋转数组的最小数字(C++/Java)

    题目: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转, ...