• spring security OAuth2 实战


    目录

    1、OAuth 介绍

    (1)OAuth 2.0授权流程

    (2)授权模式分类

    2、OAuth2的授权码模式

    (1)相关依赖引入

    (2)配置 spring security 

    (3)添加授权服务器

    (4)添加资源服务器

    3、OAuth2的简化模式

    4、OAuth2的密码模式

    5、OAuth2的客户端模式

    6、更新令牌

    7、基于 redis 存储 Token


    1、OAuth 介绍

    OAuth(Open Authorization)是一个关于授权(authorization)的开放网络标准,允许用户授权第三方应用访问存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方应用或分享他们数据的所有内容。OAuth在全世界得到广泛应用,目前的版本是2.0版。

    OAuth协议:https://tools.ietf.org/html/rfc6749

    OAuth 基本概念

    • Third-party application:第三方应用程序,又称"客户端"(client),比如京东商城
    • HTTP service:HTTP服务提供商,简称"服务提供商",比如微信
    • Resource Owner:资源所有者,又称"用户"(user),登陆用户的信息
    • User Agent:用户代理,比如浏览器。
    • Authorization server:授权服务器,即服务提供商专门用来处理授权的服务器。
    • Resource server:资源服务器,即服务提供商存放用户生成的资源的服务器。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。

    OAuth的作用就是让"客户端"安全可控地获取"用户"的授权,与"服务商提供商"进行交互。

    (1)OAuth 2.0授权流程

    以微信开放平台为例:准备工作 | 微信开放文档

    基本设计思想:OAuth 引入了一个授权层,用来分离两种不同的角色:客户端和资源所有者。资源所有者同意以后,资源服务器可以向客户端颁发令牌。客户端通过令牌,去请求数据。

    授权流程图示:

    步骤明细:

    1. 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据 code 参数;
    2. 通过 code 参数加上 AppID 和 AppSecret 等,通过 API 换取 access_token;// 微信方生成token
    3. 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。

    (2)授权模式分类

    客户端必须得到用户的授权(authorization grant),才能获得令牌(access token)。OAuth 2.0 对于如何颁发令牌有四种方式:

    1. 授权码模式(authorization code)
    2. 密码模式(resource owner password credentials)
    3. 简化(隐式)模式(implicit)
    4. 客户端模式(client credentials)

    不论哪一种授权方式,第三方应用申请令牌之前,都必须先到授权系统备案,注册自己的身份,然后会获取两个身份识别码:客户端 ID(client ID)和客户端密钥(client secret)。

    2、OAuth2的授权码模式

    授权码(authorization code)方式,指第三方应用向授权服务方先申请授权码,然后用授权码获取令牌。授权码模式是最常用的授权流程,安全性高,适用于有后端的 Web 应用。授权码虽然通过前端传送,但令牌储存在后端,并且所有与资源服务器的通信都由后端完成,对前端屏蔽,从而可以避免令牌泄漏。

     步骤总结:

    1. // 1-获取授权码
    2. http://localhost:8080/oauth/authorize?response_type=code&client_id=clientA&redirect_uri=http://www.baidu.com&scope=all
    3. // 2-用户登陆后,返回授权码
    4. https://www.baidu.com/?code=ru2Ye2
    5. // 3-通过授权码获取token

    请求服务方的提供授权码——>用户授权——>服务方返回授权码——>通过授权码获取 access_token ——> 通过 access_token 访问资源

    (1)相关依赖引入

    首先需要引入security 和 oauth2 的相关依赖,spring boot 依赖引入示例:

    1. <!-- Spring Security 配置 -->
    2. <dependency>
    3. <groupId>org.springframework.boot</groupId>
    4. <artifactId>spring-boot-starter-security</artifactId>
    5. </dependency>
    6. <dependency>
    7. <groupId>org.springframework.security.oauth</groupId>
    8. <artifactId>spring-security-oauth2</artifactId>
    9. <version>2.3.4.RELEASE</version>
    10. </dependency>

    如果是微服务,对应的 spring cloud 依赖引入示例(security 也要引入):

    1. <dependency>
    2. <groupId>org.springframework.cloud</groupId>
    3. <artifactId>spring-cloud-starter-oauth2</artifactId>
    4. </dependency>

    (2)配置 spring security 

    WebSecurityConfigurerAdapter 是自定义的 spring security 配置文件,在  spring security 基本功能实现的基础上,配置请求拦截规则,要求对所有的 /oauth/** 接口放行 

    1. import com.swadian.userdemo.service.MyUserDetailsService;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.context.annotation.Bean;
    4. import org.springframework.context.annotation.Configuration;
    5. import org.springframework.context.annotation.Lazy;
    6. import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    7. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    8. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    9. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    10. import org.springframework.security.crypto.password.PasswordEncoder;
    11. @Configuration // 标记为注解类
    12. public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
    13. @Autowired
    14. @Lazy // 解决循环依赖
    15. private MyUserDetailsService userService;
    16. @Bean // 编码
    17. public PasswordEncoder passwordEncoder() {
    18. return new BCryptPasswordEncoder();
    19. }
    20. @Override // 注入用户信息
    21. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    22. //设置UserDetailsService的实现类
    23. auth.userDetailsService(userService);
    24. }
    25. @Override
    26. protected void configure(HttpSecurity http) throws Exception {
    27. http.formLogin().permitAll() // 表单登陆
    28. .and()
    29. .authorizeRequests()
    30. .antMatchers("/oauth/**").permitAll() // 授权oauth下的所有接口
    31. .anyRequest().authenticated()
    32. .and().logout().permitAll() // 登出
    33. .and().csrf().disable();
    34. }
    35. }

    配置用户信息是权限系统的基本要求,需要根据用户信息进行身份验证,授权校验

    1. import org.springframework.beans.factory.annotation.Autowired;
    2. import org.springframework.security.core.authority.AuthorityUtils;
    3. import org.springframework.security.core.userdetails.User;
    4. import org.springframework.security.core.userdetails.UserDetails;
    5. import org.springframework.security.core.userdetails.UserDetailsService;
    6. import org.springframework.security.core.userdetails.UsernameNotFoundException;
    7. import org.springframework.security.crypto.password.PasswordEncoder;
    8. import org.springframework.stereotype.Service;
    9. @Service
    10. public class MyUserDetailsService implements UserDetailsService {
    11. @Autowired
    12. private PasswordEncoder passwordEncoder;
    13. @Override
    14. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    15. String password = passwordEncoder.encode("123456"); // 密码
    16. return new User("admin",
    17. password,
    18. AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    19. }
    20. }

    模拟需要授权的接口,一旦接口请求成功,会返回一串字符串,示例如下:

    1. @RestController
    2. @RequestMapping("/admin")
    3. public class AdminController {
    4. @GetMapping("/test")
    5. public String test() {
    6. return "Spring Security Test";
    7. }
    8. }

    (3)添加授权服务器

    授权服务器具有以下核心端点

    添加授权服务器配置,@EnableAuthorizationServer 开启授权服务器,注册可用的客户端,并在授权模式中添加 authorization_code ,表示授权码模式

    1. import org.springframework.beans.factory.annotation.Autowired;
    2. import org.springframework.context.annotation.Configuration;
    3. import org.springframework.security.crypto.password.PasswordEncoder;
    4. import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
    5. import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
    6. import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
    7. @Configuration
    8. @EnableAuthorizationServer
    9. public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    10. @Autowired
    11. private PasswordEncoder passwordEncoder;
    12. @Override
    13. public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    14. clients.inMemory()
    15. .withClient("clientA") //配置客户端id client_id
    16. .secret(passwordEncoder.encode("123456")) //配置client-secret
    17. .accessTokenValiditySeconds(3600) //配置访问token的有效期
    18. .refreshTokenValiditySeconds(864000) //配置刷新token的有效期
    19. .redirectUris("http://www.baidu.com") //配置redirect_uri,授权成功后跳转
    20. .scopes("all") //配置申请的权限范围
    21. .authorizedGrantTypes("authorization_code");//配置grant_type,表示授权类型
    22. }
    23. }

    (4)添加资源服务器

    配置资源服务器,明确进行授权的资源

    1. import org.springframework.context.annotation.Configuration;
    2. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    3. import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
    4. import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
    5. @Configuration
    6. @EnableResourceServer
    7. public class ResourceServiceConfig extends ResourceServerConfigurerAdapter {
    8. @Override
    9. public void configure(HttpSecurity http) throws Exception {
    10. http.authorizeRequests()
    11. .anyRequest().authenticated()
    12. .and()
    13. .requestMatchers().antMatchers("/admin/**"); // 需要验权资源
    14. }
    15. }

    测试流程

    启动 SpringBoot 项目,在浏览器端请求授权服务器进行授权,输入以下访问链接

    http://localhost:8080/oauth/authorize?response_type=code&client_id=clientA&redirect_uri=http://www.baidu.com&scope=all

    http://localhost:8080/oauth/authorize?response_type=code&client_id=clientA&redirect_uri=http://www.baidu.com&scope=all

    授权服务器需要进行登陆,输入用户名和密码进行登陆

    用户登陆成功后,跳转到授权页面

    点击 Approve 进行授权确认,确认后会携带一个code,跳转到重定向地址

    接下来使用code(授权码),获取登陆令牌,使用 postman 进行模拟请求,授权服务器获取令牌的接口为

    http://127.0.0.1:8080/oauth/token

     参数 grant_type:authorization_code,redirect_uri:百度(随便填的,必填),code:上步骤返回的code

    请求成功后,会返回 json 格式的数据,其中就有我们需要的令牌

    1. {
    2. "access_token": "3c26e355-a011-4b0f-a6f6-91a724fd0153",
    3. "token_type": "bearer",
    4. "expires_in": 3599,
    5. "scope": "all"
    6. }
    • grant_type :授权类型,authorization_code,表示授权码模式 
    • code :授权码,刚刚获取的code,注意:授权码只能使用一次,后续需要重新申请 
    • client_id :客户端标识 
    • redirect_uri :跳转url,一定要和申请授权码时用的redirect_uri一致 
    • scope :授权范围

    如果认证失败,服务端会返回 401 Unauthorized

    接下来,使用令牌(access_token)去资源服务器访问授权资源,资源能够正常访问

    或者,直接在资源后携带 access_token

    或者,在请求头中,添加 Authorization 授权信息,注意要带上 token 类型 bearer

    至此,spring security OAuth2 的授权码模式完成

    3、OAuth2的简化模式

    简化(隐式)模式,允许直接向前端颁发令牌,这种方式没有授权码这个中间步骤,所以称为(授权码)"隐藏式"(implicit)。该模式直接在浏览器中向授权服务器申请令牌,没有"授权码"步骤,所有步骤都在浏览器中完成,同时令牌对访问者也是可见的。

    简化模式直接把令牌传给前端,该方式很不安全。因此,只能用于一些安全性要求不高的场景,并且令牌设置的有效期必须非常短,通常只是会话期间(session)有效,一旦浏览器关掉,令牌就就失效了。

    使用场景:纯前端应用

    步骤总结:

    请求服务提供方的授权 ——>直接获取 access_token ——> 携带 access_token 访问资源

    代码示例:

    在上文代码的基础上,修改授权服务器的配置,在 authorizedGrantTypes 属性中添加 "implicit", //简化模式,完整的代码如下:

    1. // 完整的代码如下
    2. @Override
    3. public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    4. clients.inMemory()
    5. .withClient("clientA") //配置client_id
    6. .secret(passwordEncoder.encode("123456")) //配置client-secret
    7. .accessTokenValiditySeconds(3600) //配置访问token的有效期
    8. .refreshTokenValiditySeconds(864000) //配置刷新token的有效期
    9. .redirectUris("http://www.baidu.com") //配置redirect_uri,用于授权成功后跳转
    10. .scopes("all") //配置申请的权限范围
    11. .authorizedGrantTypes(
    12. //"authorization_code", //授权码模式,配置grant_type,表示授权类型
    13. "implicit", //简化模式
    14. //"password", //密码模式
    15. //"client_credentials",//客户端模式
    16. "refresh_token"); //更新令牌
    17. }

    启动服务,访问以下链接

    http://localhost:8080/oauth/authorize?response_type=token&client_id=clientA&redirect_uri=http://www.baidu.com&scope=all

    http://localhost:8080/oauth/authorize?response_type=token&client_id=clientA&redirect_uri=http://www.baidu.com&scope=all

    将会直接跳转到重定向页面,同时,access_token 会在跳转的地址栏中返回,中间不需要经过任何环节。

    4、OAuth2的密码模式

    如果对某个应用高度信任,用户直接使用用户名和密码申请令牌,这种方式称为"密码式"(password)。

    在这种模式中,用户必须把密码给客户端,但是客户端不得储存密码。通常在用户对客户端高度信任的场景下使用,比如客户端是操作系统的一部分。一般来说授权服务器只有在其他授权模式无法执行的情况下,才考虑使用这种模式。

    适用场景:公司自己搭建的授权服务器

    代码示例:

    在上文代码的基础上,修改 spring security 配置,在配置中增加 authenticationManagerBean

    1. import com.swadian.userdemo.service.MyUserDetailsService;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.context.annotation.Bean;
    4. import org.springframework.context.annotation.Configuration;
    5. import org.springframework.context.annotation.Lazy;
    6. import org.springframework.security.authentication.AuthenticationManager;
    7. import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    8. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    9. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    10. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    11. import org.springframework.security.crypto.password.PasswordEncoder;
    12. @Configuration // 标记为注解类
    13. public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
    14. @Autowired
    15. @Lazy // 解决循环依赖
    16. private MyUserDetailsService userService;
    17. @Bean
    18. public PasswordEncoder passwordEncoder() {
    19. return new BCryptPasswordEncoder();
    20. }
    21. @Override
    22. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    23. //设置UserDetailsService的实现类
    24. auth.userDetailsService(userService);
    25. }
    26. @Override
    27. protected void configure(HttpSecurity http) throws Exception {
    28. http.formLogin().permitAll()
    29. .and()
    30. .authorizeRequests().antMatchers("/oauth/**").permitAll()
    31. .anyRequest().authenticated()
    32. .and().logout().permitAll()
    33. .and().csrf().disable();
    34. }
    35. @Bean
    36. @Override
    37. public AuthenticationManager authenticationManagerBean() throws Exception {
    38. return super.authenticationManagerBean();
    39. }
    40. }

    然后修改授权服务器的配置,在 endpoints 配之中,添加允许使用 GET 和 POST 请求,并且允许进行表单验证,完整代码如下:

    1. import org.springframework.beans.factory.annotation.Autowired;
    2. import org.springframework.context.annotation.Configuration;
    3. import org.springframework.http.HttpMethod;
    4. import org.springframework.security.authentication.AuthenticationManager;
    5. import org.springframework.security.crypto.password.PasswordEncoder;
    6. import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
    7. import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
    8. import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
    9. import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
    10. import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
    11. @Configuration
    12. @EnableAuthorizationServer
    13. public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    14. @Autowired
    15. private PasswordEncoder passwordEncoder;
    16. @Autowired
    17. private AuthenticationManager authenticationManagerBean;
    18. @Override
    19. public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    20. endpoints.authenticationManager(authenticationManagerBean) //使用密码模式需要配置
    21. .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST); //支持 GET,POST请求
    22. }
    23. @Override
    24. public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    25. //允许表单认证
    26. security.allowFormAuthenticationForClients();
    27. }
    28. @Override
    29. public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    30. clients.inMemory()
    31. .withClient("clientA") //配置client_id
    32. .secret(passwordEncoder.encode("123456")) //配置client-secret
    33. .accessTokenValiditySeconds(3600) //配置访问token的有效期
    34. .refreshTokenValiditySeconds(864000) //配置刷新token的有效期
    35. .redirectUris("http://www.baidu.com") //配置redirect_uri,用于授权成功后跳转
    36. .scopes("all") //配置申请的权限范围
    37. .authorizedGrantTypes(//"authorization_code", //授权码模式 //配置grant_type,表示授权类型
    38. "password", //密码模式
    39. //"client_credentials",//客户端模式
    40. "refresh_token"); //更新令牌
    41. }
    42. }

    接下来获取令牌

    测试方法一:通过浏览器访问以下地址 // 需要配置支持get请求和表单验证

    http://localhost:8080/oauth/token?username=admin&password=123456&grant_type=password&client_id=clientA&client_secret=123456&scope=all

    http://localhost:8080/oauth/token?username=admin&password=123456&grant_type=password&client_id=clientA&client_secret=123456&scope=all

    访问结果如下:// 直接获取到 access_token

    测试方法二:通过 postman 进行测试 

    尝试访问授权资源

    5、OAuth2的客户端模式

    客户端模式(Client Credentials Grant)指客户端以服务器身份,向服务提供方申请授权。适用于没有前端的命令行应用,一般提供给受信任的服务器端使用。

    在上文代码的基础上,配置 grant_type 为 client_credentials,然后直接在浏览器中输入以下链接就进行验证

    http://localhost:8080/oauth/token?grant_type=client_credentials&client_id=clientA&scope=all&client_secret=123456

    http://localhost:8080/oauth/token?grant_type=client_credentials&client_id=clientA&scope=all&client_secret=123456

    验证结果如下:

    6、更新令牌

    使用 oauth2 时,如果令牌失效了,可以通过 refresh_token 的授权模式再次获取access_token,从而刷新令牌,刷新令牌可避免繁琐的重复认证

    在上边代码的基础上修改授权服务器配置,在 authorizedGrantTypes 中添加  refresh_token 类型,同时可以在 endpoints 配置中,配置 refresh_token 是否可重复使用

    1. @Configuration
    2. @EnableAuthorizationServer
    3. public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    4. @Autowired
    5. private PasswordEncoder passwordEncoder;
    6. @Autowired
    7. private MyUserDetailsService userService;
    8. @Autowired
    9. private AuthenticationManager authenticationManagerBean;
    10. @Override
    11. public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    12. endpoints.authenticationManager(authenticationManagerBean) //使用密码模式需要配置
    13. .reuseRefreshTokens(false) //refresh_token是否重复使用
    14. .userDetailsService(userService) //刷新令牌授权包含对用户信息的检查
    15. .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST); //支持 GET,POST请求
    16. }
    17. @Override
    18. public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    19. //允许表单认证
    20. security.allowFormAuthenticationForClients();
    21. }
    22. @Override
    23. public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    24. clients.inMemory()
    25. .withClient("clientA") //配置client_id
    26. .secret(passwordEncoder.encode("123456")) //配置client-secret
    27. .accessTokenValiditySeconds(3600) //配置访问token的有效期
    28. .refreshTokenValiditySeconds(864000) //配置刷新token的有效期
    29. .redirectUris("http://www.baidu.com") //配置redirect_uri,用于授权成功后跳转
    30. .scopes("all") //配置申请的权限范围
    31. .authorizedGrantTypes(//"authorization_code", //授权码模式 //配置grant_type,表示授权类型
    32. "password", //密码模式
    33. //"client_credentials",//客户端模式
    34. "refresh_token"); //更新令牌
    35. }
    36. }

    通过密码模式进行测试,在浏览器端访问以下链接

    1. http://localhost:8080/oauth/token
    2. ?username=admin
    3. &password=123456
    4. &grant_type=password
    5. &client_id=clientA
    6. &client_secret=123456
    7. &scope=all

    http://localhost:8080/oauth/token?username=admin&password=123456&grant_type=password&client_id=clientA&client_secret=123456&scope=all

    在返回报文中,有一个 refresh_token 的字段,如果需要刷新令牌,可以使用 refresh_token 访问如下链接:

    http://localhost:8080/oauth/token?grant_type=refresh_token&client_id=clientA&client_secret=123456&refresh_token=73ca27c6-69b9-4788-ab8a-edee28d0ec93

    http://localhost:8080/oauth/token?grant_type=refresh_token&client_id=clientA&client_secret=123456&refresh_token=73ca27c6-69b9-4788-ab8a-edee28d0ec93

    7、基于 redis 存储 Token

    需要引入 redis 相关的依赖

    1. <dependency>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-data-redis</artifactId>
    4. </dependency>

    修改配置文件 application.yaml ,添加 redis 配置

    1. spring:
    2. redis:
    3. host: localhost
    4. port: 6379
    5. database: 0

     编写 redis 配置类,返回 RedisTokenStore 的存储实例

    1. import org.springframework.beans.factory.annotation.Autowired;
    2. import org.springframework.context.annotation.Bean;
    3. import org.springframework.context.annotation.Configuration;
    4. import org.springframework.data.redis.connection.RedisConnectionFactory;
    5. import org.springframework.security.oauth2.provider.token.TokenStore;
    6. import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
    7. @Configuration
    8. public class RedisConfig {
    9. @Autowired
    10. private RedisConnectionFactory redisConnectionFactory;
    11. @Bean
    12. public TokenStore tokenStore() {
    13. return new RedisTokenStore(redisConnectionFactory);
    14. }
    15. }

    在授权服务器配置中指定令牌的存储策略为 Redis

    1. @Configuration
    2. @EnableAuthorizationServer
    3. public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    4. @Autowired
    5. private PasswordEncoder passwordEncoder;
    6. @Autowired
    7. private TokenStore tokenStore;
    8. @Autowired
    9. private MyUserDetailsService userService;
    10. @Autowired
    11. private AuthenticationManager authenticationManagerBean;
    12. @Override
    13. public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    14. endpoints.authenticationManager(authenticationManagerBean) //使用密码模式需要配置
    15. .tokenStore(tokenStore) // 指定token存储到redis
    16. .reuseRefreshTokens(false) //refresh_token是否重复使用
    17. .userDetailsService(userService) //刷新令牌授权包含对用户信息的检查
    18. .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST); //支持 GET,POST请求
    19. }
    20. }

    接下来,使用密码模式进行测试,访问如下链接

    http://localhost:8080/oauth/token?username=admin&password=123456&grant_type=password&client_id=clientA&client_secret=123456&scope=all

    查看下 redis 是否存储了 token

    至此,redis  存储 Token 验证成功

  • 相关阅读:
    Koa: 打造高效、灵活的Node.js后端 (介绍与环境部署)
    KafkaConsumer 消费逻辑
    ReactDOM.render在react源码中执行之后发生了什么?
    机器人多设备局域网可通调试
    MySQL表级锁、行级锁与多粒度锁(意向锁)
    bootstrap 主题
    微信小程序介绍
    Shell脚本之if的用法
    ShareSDK 第三方平台注册指南
    树莓派智能语音助手之TTS - pyttsx3 + espeak
  • 原文地址:https://blog.csdn.net/swadian2008/article/details/126820306