Springboot之OncePerRequestFilter 过滤器
原文链接:https://www.cnblogs.com/javalinux1/p/16389683.html
类说明
OncePerRequestFilter能够确保在一次请求只通过一次filter,而不需要重复执行。
记录到问题
在使用springSecurity的过程中遇到已经放权校验的url,在请求头依然携带有效的token信息,依然被拦截。
解决方案
使用JwtAuthenticationTokenFilter继承OncePerRequestFilter,重写doFilterInternal()方法,将请求头中的token信息去掉。
实现代码如下。
@Component
@Slf4j
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
{
@Autowired
private TokenService tokenService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException
{
log.info("当前访问的地址:{}", request.getRequestURI());
String url = request.getRequestURI();
// 校验请求的url是否在忽略鉴权的url中
if (checkUrl(url)) {
request = new HttpServletRequestWrapper(request) {
private Set<String> headerNameSet;
@Override
public Enumeration<String> getHeaderNames() {
if (headerNameSet == null) {
// first time this method is called, cache the wrapped request's header names:
headerNameSet = new HashSet<>();
Enumeration<String> wrappedHeaderNames = super.getHeaderNames();
while (wrappedHeaderNames.hasMoreElements()) {
String headerName = wrappedHeaderNames.nextElement();
if (!"Authorization".equalsIgnoreCase(headerName)) {
headerNameSet.add(headerName);
}
}
}
return Collections.enumeration(headerNameSet);
}
@Override
public Enumeration<String> getHeaders(String name) {
if ("Authorization".equalsIgnoreCase(name)) {
return Collections.<String>emptyEnumeration();
}
return super.getHeaders(name);
}
@Override
public String getHeader(String name) {
if ("Authorization".equalsIgnoreCase(name)) {
return null;
}
return super.getHeader(name);
}
};
}
LoginUser loginUser = tokenService.getLoginUser(request);
if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication()))
{
tokenService.verifyToken(loginUser);
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
chain.doFilter(request, response);
}
/**
* 校验路径是否是要忽略鉴权路径
* @param url
*/
private boolean checkUrl(String url){
for (String method : PatternsConstant.PATTERNS) {
if (!method.equals("/**") && !method.equals("**")) {
if (method.endsWith("/**")){
method = method.substring(0, method.length() - 3);
if (url.startsWith(method)) {
return true;
}
}else {
if (url.equals(method)) {
return true;
}
}
}else {
return false;
}
}
return false;
}
}
此处将忽略鉴权的url写在一个具体的类中,否则上面的方法拿不到需要忽略鉴权的url。
————————————————
版权声明:本文为CSDN博主「布道谷」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44636027/article/details/109697469