日常bb 日常bb
首页
文章
笔记
冥思
其他
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

日常bb

想起来全是问题,做起来才有答案。
首页
文章
笔记
冥思
其他
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Java

  • Redis

  • Spring

    • 基础使用

    • Spring Security

      • Spring Security学习总结
      • Spring Security
      • Spring Security OAuth2
      • 实战单体应用(认证授权服务+资源服务)
      • 实战模块化(认证授权服务+资源服务)
        • 项目结构
        • security-common
        • auth-demo
          • TokenConfig
          • AuthorizationServerConfig
        • resources-demo
        • 测试
      • Spring Security OAuth2自定义授权模式
    • 收藏

  • 工具

  • 概念

  • 容器

  • 实战

  • 文章
  • Spring
  • Spring Security
rcbb
2022-10-05
目录

实战模块化(认证授权服务+资源服务)

# 实战模块化(认证授权服务+资源服务)

在微服务的架构下,对单体应用的认证授权服务和资源服务需要进行拆分和模块化处理。

该内容基于上一篇:实战单体应用(认证授权服务+资源服务) (opens new window)

# 项目结构

主要是将整个Spring Security OAuth2共用的配置写到security-common中,这样后期使用非常方便,只需要创建普通Spring Web项目,然后引用security-common模块即可。

SpringSecurity-demo
---auth-demo
---resources-demo
---security-common
1
2
3
4

SpringSecurity-demo Github地址 (opens new window)

# security-common

ResourceServerConfig

@Configuration
@EnableResourceServer
// 开启注解鉴权
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Bean
    @Primary
    public ResourceServerTokenServices tokenServices() {
        // 如果资源服务和认证服务在一起可以使用 DefaultTokenServices 进行本地校验
        // 使用远程服务请求授权服务器校验token,必须指定url,client_id,client_secret
        RemoteTokenServices services = new RemoteTokenServices();
        services.setCheckTokenEndpointUrl("http://127.0.0.1:3000/oauth/check_token");
        services.setClientId("rcbb");
        services.setClientSecret("rcbb");
        return services;
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources
                // 验证令牌的服务
                .tokenServices(tokenServices())
                .stateless(true);
    }

    //配置资源服安全规则
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                // 授权的请求
                .authorizeRequests()
                // 任何请求
                .anyRequest()
                // 需要身份认证
                .authenticated()
                .and().csrf().disable();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

并且使用Spring的自动装配,src/main/resources/META-INF/spring.factories配置。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  cc.rcbb.springsecurity.demo.common.config.ResourceServerConfig
1
2

# auth-demo

认证服务的主要几个配置AuthorizationServerConfig、TokenConfig、WebSecurityConfig。

# TokenConfig

TokenConfig之前单体的时候没有单独配置,是因为默认就是使用内存存储令牌。单独拎出来是为了后续扩展。

@Configuration
public class TokenConfig {

    @Bean
    public TokenStore tokenStore() {
        // 使用内存存储令牌(普通令牌)
        return new InMemoryTokenStore();
    }

}

1
2
3
4
5
6
7
8
9
10
11

# AuthorizationServerConfig

主要内容是开放授权服远程检验token。 因为认证授权服服务和资源服务分开了,所以token无法共享,可以通过远程的方式校验Token。

还有一种思路就是通过Redis,只要认证授权服服务和资源服务是使用的是同一个Redis,那么资源服务就可自己做校验,直接通过资源服务查询Redis。

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private TokenStore tokenStore;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private ClientDetailsService clientDetailsService;
    @Autowired
    private AuthenticationManager authenticationManager;


    //令牌管理服务
    @Bean
    public AuthorizationServerTokenServices tokenService() {
        DefaultTokenServices service = new DefaultTokenServices();
        // 客户端详情服务
        service.setClientDetailsService(clientDetailsService);
        // 支持刷新令牌
        service.setSupportRefreshToken(true);
        // 令牌存储策略
        service.setTokenStore(tokenStore);
        // 令牌默认有效期2小时
        service.setAccessTokenValiditySeconds(7200);
        // 刷新令牌默认有效期3天
        service.setRefreshTokenValiditySeconds(259200);
        return service;
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        // 基于内存便于测试,使用in-memory存储
        clients.inMemory()
                // client_id
                .withClient("rcbb")
                // 未加密
                //.secret("secret")
                // 加密
                .secret(passwordEncoder.encode("rcbb"))
                // 资源列表
                //.resourceIds("res1")
                // 该client允许的授权类型authorization_code,password,refresh_token,implicit,client_credentials
                .authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit", "refresh_token")
                // 允许的授权范围
                .scopes("all", "ROLE_ADMIN", "ROLE_USER")
                // false跳转到授权页面
                //.autoApprove(false)
                //加上验证回调地址
                .redirectUris("http://rcbb.cc");
    }

    /**
     * 配置令牌的访问端点和令牌服务
     *
     * @param endpoints the endpoints configurer
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        // 配置认证管理器
        endpoints.authenticationManager(authenticationManager)
                .tokenServices(tokenService());
    }

    /**
     * @Description: 用来配置令牌端点(Token Endpoint)的安全约束
     * Token令牌默认是有签名的,并且资源服务需要验证这个签名,
     * 因此呢,你需要使用一个对称的Key值,用来参与签名计算,
     * 这个Key值存在于授权服务以及资源服务之中。
     * 或者你可以使用非对称加密算法来对Token进行签名,
     * Public Key公布在/oauth/token_key这个URL连接中,
     * 默认的访问安全规则是"denyAll()",
     * 即在默认的情况下它是关闭的,
     * 你可以注入一个标准的 SpEL 表达式到 AuthorizationServerSecurityConfigurer 这个配置中来将它开启
     * (例如使用"permitAll()"来开启可能比较合适,因为它是一个公共密钥)。
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security
                // 开放获取token key(这个是做JWT的时候开放的!也就是资源服可以通过这个请求得到JWT加密的key,目前这里没什么用,可以不用配置)
                .tokenKeyAccess("permitAll()")
                // 开放远程token检查
                .checkTokenAccess("permitAll()")
                // 允许client使用form的方式进行authentication的授权
                .allowFormAuthenticationForClients();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

# resources-demo

基本上资源服务就没什么内容了,核心配置直接引入security-common模块即可。

现在就只剩资源UserController了。

@RestController
@RequestMapping("/user")
public class UserController {

    @PreAuthorize("hasAuthority('user_add')")
    @PostMapping
    public String save() {
        return "save() success";
    }

    @PreAuthorize("hasAuthority('user_remove')")
    @DeleteMapping
    public String remove() {
        return "remove() success";
    }

    @PreAuthorize("hasAuthority('user_update')")
    @PutMapping
    public String update() {
        return "update() success";
    }

    @Secured("ROLE_ADMIN")
    @GetMapping
    public String list() {
        return "list() success";
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 测试

启动auth-demo和resources-demo服务。

首先先通过账号密码获取token。

通过账号密码获取

然后再携带token访问资源服务,需要注意是资源服务是另外一个服务。

访问资源服务

测试成功。


#Spring Security
上次更新: 10/7/2022
实战单体应用(认证授权服务+资源服务)
Spring Security OAuth2自定义授权模式

← 实战单体应用(认证授权服务+资源服务) Spring Security OAuth2自定义授权模式→

最近更新
01
Sign in with Apple(苹果授权登陆)
12-29
02
Nacos容器化
11-11
03
好用的截图工具
11-10
更多文章>
Theme by Vdoing | Copyright © 2021-2022 日常bb | 鄂ICP备17023998号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式