当前位置:   article > 正文

SpringSecurity+OAuth2.0 搭建认证中心和资源服务中心_资源服务器 remotetokenservices

资源服务器 remotetokenservices

目录

 

1. OAuth2.0 简介

2. 代码搭建 

2.1 认证中心(8080端口)

2.2 资源服务中心(8081端口)

3. 测试结果


 

1. OAuth2.0 简介

OAuth 2.0(开放授权 2.0)是一个开放标准,用于授权第三方应用程序访问用户在资源所有者(用户)的帐户上存储的受保护资源,而无需共享用户凭据。OAuth 2.0 主要用于在互联网上安全地委托授权,广泛应用于身份验证和授权场景。

以下是 OAuth 2.0 的核心概念和流程:

  1. 角色:

    • 资源所有者(Resource Owner): 拥有受保护资源的用户。
    • 客户端(Client): 第三方应用程序,希望访问资源所有者的受保护资源。
    • 授权服务器(Authorization Server): 负责验证资源所有者并颁发访问令牌的服务器。
    • 资源服务器(Resource Server): 存储受保护资源的服务器,它可以与授权服务器相同,也可以是不同的服务器。
  2. 授权类型:OAuth2.0协议一共支持 4 种不同的授权模式:

                授权码模式:常见的第三方平台登录功能基本都是使用这种模式。

d2209e26d527475aa4a70f423492c0e1.png

                简化模式:简化模式是不需要客户端服务器参与,直接在浏览器中向授权服务器申请令牌(token),一般如果网站是纯静态页面则可以采用这种方式。

2dd09289ea6a4ff397c4508f29ee369d.png

                密码模式:密码模式是用户把用户名密码直接告诉客户端,客户端使用说这些信息向授权服务器申请令牌(token)。这需要用户对客户端高度信任,例如客户端应用和服务提供商就是同一家公司,自己做前后端分离登录就可以采用这种模式。

        

81b4344a8ff9419da640048d9458c986.png

                客户端模式:客户端模式是指客户端使用自己的名义而不是用户的名义向服务提供者申请授权,严格来说,客户端模式并不能算作 OAuth 协议要解决的问题的一种解决方案,但是,对于开发者而言,在一些前后端分离应用或者为移动端提供的认证授权服务器上使用这种模式还是非常方便的。

3e7e2196fac64fb79a779c9efd1700cb.png

2. 代码搭建 

2.1 认证中心(8080端口

导入依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.cloud</groupId>
  8. <artifactId>spring-cloud-starter-security</artifactId>
  9. <version>2.2.5.RELEASE</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.springframework.cloud</groupId>
  13. <artifactId>spring-cloud-starter-oauth2</artifactId>
  14. <version>2.2.5.RELEASE</version>
  15. </dependency>
  16. </dependencies>

只需要添加两个配置类即可

MyAuthorizationConfig类

  1. @Configuration
  2. @EnableAuthorizationServer
  3. public class MyAuthorizationConfig extends AuthorizationServerConfigurerAdapter {
  4. /**
  5. * 客户端存储策略,这里使用内存方式,后续可以存储在数据库
  6. */
  7. @Autowired
  8. private ClientDetailsService clientDetailsService;
  9. /**
  10. * Security的认证管理器,密码模式需要用到
  11. */
  12. @Autowired
  13. private AuthenticationManager authenticationManager;
  14. /**
  15. * 配置令牌访问的安全约束
  16. */
  17. @Override
  18. public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
  19. security
  20. //开启/oauth/token_key验证端口权限访问
  21. .tokenKeyAccess("permitAll()")
  22. //开启/oauth/check_token验证端口认证权限访问
  23. .checkTokenAccess("permitAll()")
  24. //表示支持 client_id 和 client_secret 做登录认证
  25. .allowFormAuthenticationForClients();
  26. }
  27. //配置客户端
  28. @Override
  29. public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
  30. //内存模式
  31. clients.inMemory()
  32. //客户端id
  33. .withClient("test")
  34. //客户端秘钥
  35. .secret(new BCryptPasswordEncoder().encode("123456"))
  36. //资源id,唯一,比如订单服务作为一个资源,可以设置多个
  37. .resourceIds("order")
  38. //授权模式,总共四种,1. authorization_code(授权码模式)、password(密码模式)、client_credentials(客户端模式)、implicit(简化模式)
  39. //refresh_token并不是授权模式,
  40. .authorizedGrantTypes("authorization_code","password","client_credentials","implicit","refresh_token")
  41. //允许的授权范围,客户端的权限,这里的all只是一种标识,可以自定义,为了后续的资源服务进行权限控制
  42. .scopes("all")
  43. //false 则跳转到授权页面
  44. .autoApprove(false)
  45. //授权码模式的回调地址
  46. .redirectUris("http://www.baidu.com"); //可以and继续添加客户端
  47. }
  48. /**
  49. * 令牌存储策略
  50. */
  51. @Bean
  52. public TokenStore tokenStore(){
  53. return new InMemoryTokenStore();
  54. }
  55. @Bean
  56. public AuthorizationServerTokenServices tokenServices() {
  57. DefaultTokenServices services = new DefaultTokenServices();
  58. //客户端端配置策略
  59. services.setClientDetailsService(clientDetailsService);
  60. //支持令牌的刷新
  61. services.setSupportRefreshToken(true);
  62. //令牌服务
  63. services.setTokenStore(tokenStore());
  64. //access_token的过期时间
  65. services.setAccessTokenValiditySeconds(60 * 60 * 2);
  66. //refresh_token的过期时间
  67. services.setRefreshTokenValiditySeconds(60 * 60 * 24 * 3);
  68. return services;
  69. }
  70. /**
  71. * 授权码模式的service,使用授权码模式authorization_code必须注入
  72. */
  73. @Bean
  74. public AuthorizationCodeServices authorizationCodeServices() {
  75. //授权码存在内存中
  76. return new InMemoryAuthorizationCodeServices();
  77. }
  78. /**
  79. * 配置令牌访问的端点
  80. */
  81. @Override
  82. public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
  83. endpoints
  84. //授权码模式所需要的authorizationCodeServices
  85. .authorizationCodeServices(authorizationCodeServices())
  86. //密码模式所需要的authenticationManager
  87. .authenticationManager(authenticationManager)
  88. //令牌管理服务,无论哪种模式都需要
  89. .tokenServices(tokenServices())
  90. //只允许POST提交访问令牌,uri:/oauth/token
  91. .allowedTokenEndpointRequestMethods(HttpMethod.POST);
  92. }
  93. }

SecurityConfig类

  1. @Configuration
  2. @EnableWebSecurity
  3. public class SecurityConfig extends WebSecurityConfigurerAdapter {
  4. /**
  5. * 加密算法
  6. */
  7. @Bean
  8. PasswordEncoder passwordEncoder() {
  9. return new BCryptPasswordEncoder();
  10. }
  11. @Override
  12. protected void configure(HttpSecurity http) throws Exception {
  13. //todo 允许表单登录
  14. http.authorizeRequests()
  15. .anyRequest().authenticated()
  16. .and()
  17. .formLogin()
  18. .loginProcessingUrl("/login")
  19. .permitAll()
  20. .and()
  21. .csrf()
  22. .disable();
  23. }
  24. @Override
  25. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  26. //从内存中加载用户,实际生产中需要从数据库中加载
  27. auth.inMemoryAuthentication()
  28. .withUser("admin")
  29. .password(new BCryptPasswordEncoder().encode("123456"))
  30. .roles("admin");//后面可以跟and连接
  31. }
  32. /**
  33. * AuthenticationManager对象在OAuth2认证服务中要使用,提前放入IOC容器中
  34. * Oauth的密码模式需要
  35. */
  36. @Override
  37. @Bean
  38. public AuthenticationManager authenticationManagerBean() throws Exception {
  39. return super.authenticationManagerBean();
  40. }
  41. }

2.2 资源服务中心(8081端口)

导入依赖和认证中心相同,添加一个配置类ResourceServerConfig

  1. @Configuration
  2. @EnableResourceServer
  3. public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
  4. /**
  5. * 配置令牌校验服务,客户端携带令牌访问资源,作为资源端必须检验令牌的真伪
  6. * TODO 使用JWT作为TOKEN则不必远程调用check_token校验
  7. */
  8. @Bean
  9. public RemoteTokenServices tokenServices() {
  10. //远程调用授权服务的check_token进行令牌的校验
  11. RemoteTokenServices services = new RemoteTokenServices();
  12. // /oauth/check_token 这个url是认证中心校验的token的端点
  13. services.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
  14. //客户端的唯一id
  15. services.setClientId("test");
  16. //客户端的秘钥
  17. services.setClientSecret("123456");
  18. return services;
  19. }
  20. /**
  21. * 配置资源id和令牌校验服务
  22. */
  23. @Override
  24. public void configure(ResourceServerSecurityConfigurer resources) {
  25. //配置唯一资源id
  26. resources.resourceId("order")
  27. //配置令牌校验服务
  28. .tokenServices(tokenServices());
  29. }
  30. /**
  31. * 配置security的安全机制
  32. */
  33. @Override
  34. public void configure(HttpSecurity http) throws Exception {
  35. //#oauth2.hasScope()校验客户端的权限,这个all是在客户端中的scope
  36. http.authorizeRequests()
  37. .antMatchers("/**").access("#oauth2.hasScope('all')")
  38. .anyRequest().authenticated();
  39. }
  40. }

测试接口

  1. @RestController
  2. public class TestController {
  3. @GetMapping("/test")
  4. public String hello() {
  5. return "hello world";
  6. }
  7. }

3. 测试结果

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

登录,账号admin,密码123456,然后获取授权码

91d104819cdb427ebf512d7e2cf07256.png

4de8d882006949ffbce319a761013c5f.png

获取令牌

 c5640e5e25154cc3a1fe94452145ca97.png

访问资源中心

 未携带令牌测试结果

0072c86b9b65418aac4a96b5b2563639.png

携带令牌测试结果

 1b134c5721e34ff5a1115b2be86cb947.png

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/199885
推荐阅读
相关标签
  

闽ICP备14008679号