书接上回的代码,在用户安全认证方面的过滤器介绍在下面,spring 还可以使用其他方式定义过滤器,后面介绍。
.addFilterBefore(authenticationTokenFilter,UsernamePasswordAuthenticationFilter.class)
// 添加CORS filter
.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class)
.addFilterBefore(corsFilter, LogoutFilter.class)
- 在UsernamePasswordAuthenticationFilter前面增加authenticationTokenFilter过滤器
- 在JwtAuthenticationTokenFilter前面增加corsFilter
- 在LogoutFilter前面增加corsFilter
其中UsernamePasswordAuthenticationFilter是spring security默认的过滤器链
上面的代码,最终的过滤器链顺序
CORS 处理(corsFilter)→ 最优先
JWT 认证(authenticationTokenFilter)
用户名密码认证(UsernamePasswordAuthenticationFilter)
退出登录(LogoutFilter)
corsFilter 实现
在 ResourcesConfig 类
public CorsFilter corsFilter()
{
CorsConfiguration config = new CorsConfiguration();
// 设置访问源地址
config.addAllowedOriginPattern("*");
// 设置访问源请求头
config.addAllowedHeader("*");
// 设置访问源请求方法
config.addAllowedMethod("*");
// 有效期 1800秒
config.setMaxAge(1800L);
// 添加映射路径,拦截一切请求
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
// 返回新的CorsFilter
return new CorsFilter(source);
}
首先明确什么是跨域请求
跨域请求(Cross-Origin Request)是指浏览器从一个域名的网页向另一个域名的服务器发起HTTP请求。出于安全考虑,浏览器默认会阻止这种跨域请求,这被称为"同源策略"(Same-Origin Policy)。
上面的策略很宽松,允许各种形式的跨域请求。
JwtAuthenticationTokenFilter 实现
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException
{
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);
}
- 用户带有token信息访问url
- 调用verifyToken进行token验证
- 认证通过后将用户信息保存在 SecurityContextHolder.getContext() 上下文中,这样在编写代码时可以通过getLoginUser方法获取到用户信息。
UsernamePasswordAuthenticationFilter
UsernamePasswordAuthenticationFilter 不会针对所有url,针对用户登录操作,匹配/login的请求
LogoutFilter
调用.logout(logout -> logout.logoutUrl(“/logout”).logoutSuccessHandler(logoutSuccessHandler)) 的退出逻辑。