前言

tokenExtractor()这玩意字面意思叫Token提取,确实,这玩意就是干这个的,就是提取Token的,因为我们狭义的认为Token是存放在请求头中的Authorization中的,但是并不只有这一种,共有三种token存放方式,如下!

1.在Header中携带
Header:
Authentication:Bearer xxxxx-xxx-xxx-xxx-xxxxxx

2.拼接在url中作为requestParam
​​​ http://localhost:9000/pay/1?access_token=xxxxx-xxx-xxx-xxx-xxxxxx​

3 在form表单中携带 http://xxx.xxx.xxx.xxx:9000/pay/1
form param:
access_token=xxxxx-xxx-xxx-xxx-xxxxxx

在我们资源服不配置tokenExtractor()的时候默认是使用TokenExtractor的唯一默认实现类BearerTokenExtractor,调用extract方法!,这个BearerTokenExtractor类中的逻辑很简单,就是提取token,上源码!

BearerTokenExtractor源码分析

SpringSecurityOAuth2中resources.tokenExtractor();介绍、使用_请求头


核心就三个方法extract为主方法,先调用extractToken,此方法进去调用extractHeaderToken方法,extractHeaderToken这个方法就是在请求投中提取Authorization的值返回,如果没有在请求头中获取到token的话,那么回到extractToken这个方法中,这个方法根据extractHeaderToken这个返回值的情况尝试在request parameter和form param中提取token。这就是BearerTokenExtractor的核心逻辑

resources.tokenExtractor()使用

说到使用,那么就需要先搞清楚使用场景。第一个可以编写我们自己的token提取规则,如我们可以指定其他请求头中的参数设置token,或者在使用其他requestParam 参数名,甚至将token存放在其他地方!还有另一种使用场景,就是不提取token!我这里就是在做不提取token的操作使用到这个逻辑的!

/**
* @author TAO
* @description: PreTokenExtractor是前置Token提取的一个操作,主要就是避免系统做一些无用的操作
* 在我们系统中,存在一些直接放行的接口,那么这些接口是无需做Token提取的,因为,这些放行的接口不用做鉴权,也基本上不会携带Token
* BearerTokenExtractor:默认的BearerTokenExtractor的作用就是在不同的Token携带位置提取Token
* 如Header、requestParam、from param中,那么我们放行的URL无需鉴权,所以可以省略这个提取过程,那么就有了这个类的产生!忽略系统放行URL的Token提取
* @date 2021/4/11 17:36
*/
@Component
@RequiredArgsConstructor
public class PreTokenExtractor extends BearerTokenExtractor {

@Value("${server.servlet.context-path:}")
@Getter
private String context_path;//得到系统配置的contex-path(项目路径),如果配置了使用配置的值,如果没配置防止包括使用默认值null

private final PathMatcher pathMatcher = new AntPathMatcher();

private final PermitAllUrlProperties PermitAllUrls;//得到当前服务器所有放行URL

@Override
public Authentication extract(HttpServletRequest request) {
boolean match=false;//如果当前请求的URL是在当前服务器放行的URL中,则无需做Token的提取
if(StringUtils.isEmpty(context_path)){
match = PermitAllUrls.getPermitAllUrls().stream().anyMatch(url -> pathMatcher.match(url, request.getRequestURI()));
}else{
//由于这里request.getRequestURI()中得到的是全路径,也就是设置了context-path后就会将完整请求URL拿到,
// 所以,这里需要特殊处理,而不是向PermitAllUrlProperties中,可以不管context-path
match = PermitAllUrls.getPermitAllUrls().stream()
.anyMatch(url -> pathMatcher.match(context_path+url, request.getRequestURI()));
}
//返回true不做Token提取,否则使用SpringSecurityOAuth2默认Token提取策略
return match ? null : super.extract(request);
}

}

相信通过我这篇文章应该更加清楚resources.tokenExtractor()的作用了!