OAuth2整合微服务安全学习笔记
其他
2021-02-28 15:31:05
阅读次数: 0
使用jwt替换默认uuid的token
授权服务器修改
- 授权服务器添加jwt的tokenStore及tokenEnhancer
@Bean
public TokenStore tokenStore(){
return new JwtTokenStore(tokenEnhancer()) ;
}
// 这里注入到spring容器,否则资源服务器启动是,获取tokenKey时报404
// 只有存在jwtTokenEnhancer的bean在容器中TokenKeyEndpoint端点才会发布
@Bean
public JwtAccessTokenConverter tokenEnhancer() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("123456");
return converter ;
}
- AuthorizationServerSecurityConfigurer配置tokenKeyAccess发布获取tokenKey端点
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
// 获取tokenKey接口
.tokenKeyAccess("isAuthenticated()")
// 检验token是否合法,这里如果不设置,资源服务器将无法进行token校验
.checkTokenAccess("isAuthenticated()");
}
- AuthorizationServerEndpointsConfigurer配置使用tokenStore和tokenEnhancer
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
// 设置用来支持前四种授权类型的(用户名密码)
.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancer())
.authenticationManager(authenticationManager)
// 服务端如果要支持refresh则必须设置userDetailService
// 这里用来支持refresh_token授权类型的(只有用户名)
.userDetailsService(userDetailsService)
;
}
网关服务器修改
- 添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
- 删除自定义filter
- 添加配置
# 获取验签token的tokenKey地址(授权服务器)
security.oauth2.resource.jwt.key-uri=http://localhost:7777/oauth/token_key
# 身份认证的信息
security.oauth2.client.client-id=zuul_server
security.oauth2.client.client-secret=secret
- 添加网关安全配置
@Configuration
@EnableResourceServer
public class GatewaySecurityConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/oauth/**").permitAll()
.anyRequest().authenticated();
}
}
微服务端修改
- 添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
- 添加token验证配置(因为此时传递过来的是token而不是放在header中的明文,所以也需要校验)
# 获取验签token的tokenKey地址(授权服务器)
security.oauth2.resource.jwt.key-uri=http://localhost:7777/oauth/token_key
security.oauth2.client.client-id=order_service
security.oauth2.client.client-secret=secret
- 启动类添加@EnableResourceServer注解
@EnableResourceServer
@EnableDiscoveryClient
@SpringBootApplication
public class OrderServiceApiApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApiApplication.class, args) ;
}
}
- Controller请求方法通过@AuthenticationPrincipal String username获取
@GetMapping("/hello")
public String hello(@AuthenticationPrincipal String username){
return "hello world" ;
}
- 微服务之前的调用token传递我们可以使用OAuth2RestTemplate发送请求即可
@Bean
public OAuth2RestTemplate oAuth2RestTemplate(OAuth2ProtectedResourceDetails resource, OAuth2ClientContext context){
return new OAuth2RestTemplate(resource, context) ;
}
网关上做权限认证
- 在网关配置类中自定义权限校验表达式#permissionService.hasPermission(request, authentication)
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/oauth/**").permitAll()
.anyRequest().access("#permissionService.hasPermission(request, authentication)");
}
- 编写校验权限实现类
public interface PermissionService {
boolean hasPermission(HttpServletRequest request, Authentication authentication) ;
}
@Slf4j
@Service
public class PermissionServiceImpl implements PermissionService {
@Override
public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
return checkPermission(request, authentication);
}
private boolean checkPermission(HttpServletRequest request, Authentication authentication){
log.info("===> uri : {}", request.getRequestURI());
log.info("===> authentication :{}", authentication);
return RandomUtils.nextInt() %2 ==0 ;
}
}
- 编写自定义权限表达式处理器
@Component
public class GatewayWebSecurityExpressionHandler extends OAuth2WebSecurityExpressionHandler {
@Autowired
private PermissionService permissionService ;
@Override
protected StandardEvaluationContext createEvaluationContextInternal(Authentication authentication, FilterInvocation invocation) {
StandardEvaluationContext evaluationContextInternal = super.createEvaluationContextInternal(authentication, invocation);
evaluationContextInternal.setVariable("permissionService", permissionService);
return evaluationContextInternal ;
}
}
- 将自定义表达式处理器配置到ResourceServerSecurityConfigurer的expressionHandler中
@Configuration
@EnableResourceServer
public class GatewaySecurityConfig extends ResourceServerConfigurerAdapter {
@Autowired
private GatewayWebSecurityExpressionHandler gatewayWebSecurityExpressionHandler ;
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.expressionHandler(gatewayWebSecurityExpressionHandler) ;
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/oauth/**").permitAll()
.anyRequest().access("#permissionService.hasPermission(request, authentication)");
}
}
转载自blog.csdn.net/yichengjie_c/article/details/112139013