Springboot之OncePerRequestFilter用法及说明
更新时间:2026年06月11日 15:03:35 作者:布道谷
SpringBoot中OncePerRequestFilter应用及自定义JwtAuthenticationTokenFilter实现一次请求只通过一次filter,结合springSecurity优化鉴权流程,提高系统性能
Springboot之OncePerRequestFilter
类说明
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。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
Spring Boot 集成Redisson实现分布式锁详细案例
这篇文章主要介绍了Spring Boot 集成Redisson实现分布式锁详细案例,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下2022-08-08
java 反射调用Service导致Spring注入Dao失效的解决方案
这篇文章主要介绍了java 反射调用Service导致Spring注入Dao失效的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-08-08
深入解析Spring MVC中拦截器Interceptor的实现原理和应用场景
在 Spring 生态中,拦截器(Interceptor) 是实现上述横切关注点(Cross-Cutting Concerns)的标准机制之一,它作为 Spring MVC 的核心组件,提供了对 Controller 层请求的精细化控制能力,下面小编就和大家深入介绍一下吧2025-12-12


最新评论