spring cloud gateway整合OAuth2实现自定义鉴权
1、OAuth2里面有很多个TokenStore的实现,例如RedisTokenStore,JdbcTokenStore等等,本文以RedisTokenStore实现。2、自定义CustomAuthorizationManager类实现ReactiveAuthorizationManager接口,重写check()方法3、关键代码如下@Component@Slf4jpublic class Cus
·
1、OAuth2里面有很多个TokenStore的实现,例如RedisTokenStore,JdbcTokenStore等等,本文以RedisTokenStore实现。
2、自定义CustomAuthorizationManager类实现ReactiveAuthorizationManager接口,重写check()方法
3、关键代码如下
@Component
@Slf4j
public class CustomAuthorizationManager implements ReactiveAuthorizationManager<AuthorizationContext> {
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Autowired
private RedisTemplate redisTemplate;
/**
* Determines if access is granted for a specific authentication and object.
*
* @param authenticationMono the Authentication to check
* @param object the object to check
* @return an decision or empty Mono if no decision could be made.
*/
@Override
public Mono<AuthorizationDecision> check(Mono<Authentication> authenticationMono, AuthorizationContext object) {
ServerWebExchange exchange = object.getExchange();
String requestPath = exchange.getRequest().getURI().getPath();
log.debug("当前请求路径:{}", requestPath);
PathMatcher pathMatcher = new AntPathMatcher();
//校验当前请求的url是否在白名单内
Set<String> whiteUrlList = redisTemplate.opsForSet().members(RedisConstant.WHITE_URL_LIST);
if (CollectionUtil.isNotEmpty(whiteUrlList)){
for (String whiteUrl : whiteUrlList) {
if (pathMatcher.match(whiteUrl, requestPath)) {
//将请求头的token移除,避免授权服务校验token
ServerHttpRequest request = exchange.getRequest().mutate()
.headers(httpHeaders -> httpHeaders.remove("Authorization")).build();
log.debug("url: {}, path: {},白名单地址直接放行,并将当前的请求头的token移除",whiteUrl,requestPath);
exchange.mutate().request(request).build();
return Mono.just(new AuthorizationDecision(true));
}
}
}
RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
String authorizationToken = exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
log.debug("当前请求头Authorization中的值:{}",authorizationToken);
if (StringUtils.isBlank(authorizationToken)) {
log.warn("当前请求头Authorization中的值不存在");
return Mono.just(new AuthorizationDecision(false));
}
String token = authorizationToken.replace(OAuth2AccessToken.BEARER_TYPE + " ", "");
OAuth2Authentication oAuth2Authentication = redisTokenStore.readAuthentication(token);
log.debug("当前token所拥有的OAuth2Authentication:{}", oAuth2Authentication);
Collection<GrantedAuthority> authorities = oAuth2Authentication.getAuthorities();
log.debug("当前token所拥有的权限:{}",authorities.toString());
for (GrantedAuthority authority : authorities) {
String authorityStr= authority.getAuthority();
if (pathMatcher.match(authorityStr, requestPath)) {
//设置请求头参数username
ServerHttpRequest request = exchange.getRequest().mutate()
.headers(httpHeaders -> httpHeaders.add("username",oAuth2Authentication.getName())).build();
exchange.mutate().request(request).build();
return Mono.just(new AuthorizationDecision(true));
}
}
return Mono.just(new AuthorizationDecision(false));
}
}
4、主要思路是:
a.获取当前访问路径,当前访问路径是否在配置的url白名单里面,若是则将当前请求的请求头“Authorization”移除,避免授权服务继续校验token,反之则执行以下校验
b、获取当前请求的token值,不存在则校验失败
c、通过redisTokenStore的readAuthentication方法获取当前token所拥有的权限
d、当前token拥有的权限与当前访问地址比对,比对结果则为校验结果
更多推荐
已为社区贡献2条内容
所有评论(0)