我正在使用Spring启动应用程序,我在其中定义了要执行的过滤器来管理获取和验证令牌。所以在我的Web安全类配置中,我设法做到了:
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// we don't need CSRF because our token is invulnerable
.csrf().disable()
// don't create session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
// .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
// allow anonymous resource requests
.antMatchers(HttpMethod.GET, "/", "/*.html", "/favicon.ico", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
.antMatchers("/auth/**").permitAll()
.antMatchers("/places/public").permitAll()
.anyRequest().authenticated();
// Custom JWT based security filter
httpSecurity.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
// disable page caching
httpSecurity.headers().cacheControl();
}
authenticationTokenFilterBean是一个使用@Bean注释的方法,它返回我的过滤器的一个实例:
public class JwtFilter extends OncePerRequestFilter{
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtService jwtService;
@Value("${jwt.header}")
private String authorizationHeader;
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
String token = httpServletRequest.getHeader(authorizationHeader);
String username = jwtService.getUsernameFromToken(token);
if(username!=null && SecurityContextHolder.getContext().getAuthentication() ==null){
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if(jwtService.isTokenValid(token, userDetails)){
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}
由于我正在扩展OncePerRequestFilter,每个请求只调用一次这个过滤器,这与GenericFilter不同,需要由servlet执行一次,而另一次需要Spring安全执行。
我遇到的问题是我的配置类中描述的ant匹配器也被过滤器截获,即使我允许它们使用permitAll()方法,我试图从WebSecurityConfigurerAdapter覆盖configure(WebSecurity web)方法并忽略他们但仍然没有工作。
如何配置Spring安全性以跳过针对这些请求的过滤器?我已经检查了这个问题Spring Security JWT Filter applies on all requests,但它没有解决方案。
谢谢
答案 0 :(得分:1)
更改您的WebSecurityConfiguration类,它看起来像:
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// we don't need CSRF because our token is invulnerable
.csrf().disable()
// don't create session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.anyRequest().authenticated();
// Custom JWT based security filter
httpSecurity.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
// disable page caching
httpSecurity.headers().cacheControl();
}
@Override
public void configure(WebSecurity web) throws Exception {
// Ignore spring security in these paths
web.ignoring().antMatchers("/", "/*.html", "/favicon.ico", "/**/*.html", "/**/*.css", "/**/*.js","/auth/**","/places/public");
}
您必须从HttpSecurity配置方法中删除permitAll匹配器,并将其放入WebSecurity配置方法中。
答案 1 :(得分:1)
仍然在过滤器内部进行处理,但方法更清洁。
您可以覆盖shouldNotFilter(HttpServletRequest request)
的{{1}}方法,并根据URL模式返回true来跳过过滤。
OncePerRequestFilter
答案 2 :(得分:-1)
我以这种方式避免这个问题,你可以参考:
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) throws ServletException, IOException {
if("/login".equals(req.getServletPath()) && "POST".equalsIgnoreCase(req.getMethod())){
// ......
}
filterChain.doFilter(req, res);
}