security-JWT-OAuth
微服务:Security + OAuth2 + JWT
依赖
<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>
2
3
4
5
6
7
8
令牌配置
/**
* @ClassName TokenConfig
* @Description 令牌的配置
* @Author hwzhao
* @Data 2023/9/3 19:16
* @Version 1.0
**/
@Configuration
public class TokenConfig {
/**
* JWT的密钥
* 实际项目中需要统一配置到配置文件,资源服务也需要用到
*/
String SIGNING_KEY = "hwzhao";
/**
* 令牌的存储策略
* @return
*/
@Bean
public TokenStore tokenStore() {
//使用JWTTokenStore生成JWT令牌
return new JwtTokenStore(accessTokenConverter());
}
/**
* 在JWT编码的令牌值和OAuth身份验证信息之间进行转换
* TODO:后期使用非对称加密
* @return
*/
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(SIGNING_KEY);
return converter;
}
}
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
1)JwtAccessTokenConverter
令牌增强类,用于JWT令牌和OAuth身份进行转换
2)TokenStore
令牌的存储策略,这里使用的是JwtTokenStore,使用JWT的令牌生成方式,其实还有以下两个比较常用的方式:
- RedisTokenStore:将令牌存储到Redis中,此种方式相对于内存方式来说性能更好
- JdbcTokenStore:将令牌存储到数据库中,需要新建从对应的表,有兴趣的可以尝试
3)SIGN_KEY
JWT签名的秘钥,这里使用的是对称加密,资源服务中也要使用相同的秘钥进行校验和解析JWT令牌。
授权服务器配置
1)ClientDetailsServiceConfigurer:用来配置客户端详情服务(ClientDetailsService),
随便一个客户端都可以随便接入到它的认证服务吗?答案是否定的,服务提供商会给批准接入的客户端一个身份,用于接入时的凭据,有客户端标识和客户端秘钥,在这里配置批准接入的客户端的详细信息。
2)AuthorizationServerEndpointsConfigurer:用来配置令牌(token)的访问端点和令牌服务(token services)。
3)AuthorizationServerSecurityConfigurer:用来配置令牌端点的安全约束.
安全管理配置
package cn.edu.buaa.config;
/**
* @ClassName WebSecurityConfig
* @Description TODO
* @Author hwzhao
* @Data 2023/8/26 20:02
* @Version 1.0
**/
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//配置用户信息服务
@Bean
public UserDetailsService userDetailsService() {
//这里配置用户信息,这里暂时使用这种方式将用户存储在内存中
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("zhangsan").password("123").authorities("p1").build());
manager.createUser(User.withUsername("lisi").password("456").authorities("p2").build());
return manager;
}
@Bean
public PasswordEncoder passwordEncoder() {
// //密码为明文方式
// return NoOpPasswordEncoder.getInstance();
return new BCryptPasswordEncoder();
}
//配置安全拦截机制
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/r/**")
.authenticated()
.anyRequest().permitAll()
.and()
.formLogin()
.successForwardUrl("/login-success");
http.logout().logoutUrl("/logout");
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
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
configure(HttpSecurity http)
配置说明:
- 通过
authorizeRequests()
方法来配置请求授权规则。- 使用
antMatchers()
方法指定需要进行访问控制的URL
路径模式。在这里,/r/**
表示所有以/r/
开头的 URL 都需要进行授权访问。- 使用
authenticated()
方法指定需要进行身份验证的请求。- 使用
anyRequest()
方法配置除了/r/**
以外的所有请求都不需要进行身份验证。- 使用
permitAll()
方法表示任何用户都可以访问不需要进行身份验证的URL
。- 使用
formLogin()
方法配置登录页表单认证,其中successForwardUrl()
方法指定登录成功后的跳转页面。- 使用
logout()
方法配置退出登录,其中logoutUrl()
方法指定退出登录的URL
。
关于三个configure⽅法
- configure(ClientDetailsServiceConfigurer clients)
⽤来配置客户端详情服务(ClientDetailsService),客户端详情信息在 这⾥进⾏初始化,你能够把客户端详情信息写死在这⾥或者是通过数据库来存储调取详情信息
- configure(AuthorizationServerEndpointsConfigurer endpoints)
⽤来配置令牌(token)的访问端点和令牌服务(token services)
- configure(AuthorizationServerSecurityConfigureroauthServer)
⽤来配置令牌端点的安全约束.
关于 TokenStore
- InMemoryTokenStore
默认采⽤,它可以完美的⼯作在单服务器上(即访问并发量 压⼒不⼤的情况下,并且它在失败的时候不会进⾏备份),⼤多数的项⽬都可以使⽤这个版本的实现来进⾏ 尝试,你可以在开发的时候使⽤它来进⾏管理,因为不会被保存到磁盘中,所以更易于调试。
- JdbcTokenStore
这是⼀个基于JDBC的实现版本,令牌会被保存进关系型数据库。使⽤这个版本的实现时, 你可以在不同的服务器之间共享令牌信息,使⽤这个版本的时候请注意把"spring-jdbc"这个依赖加⼊到你的 classpath当中。
- JwtTokenStore
这个版本的全称是 JSON Web Token(JWT),它可以把令牌相关的数据进⾏编码(因此对于后端服务来说,它不需要进⾏存储,这将是⼀个重⼤优势),缺点就是这个令牌占⽤的空间会⽐较⼤,如果你加⼊了⽐较多⽤户凭证信息,JwtTokenStore 不会保存任何数据。