spring cloud gateway整合OAuth2实现自定义鉴权

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拥有的权限与当前访问地址比对,比对结果则为校验结果

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值