我正在使用Spring Boot和Spring Security创建一个简单的Web应用程序。我有一个自定义过滤器来检查x-auth-token是否存在且有效。我在/src/main/resources/static
文件夹下有静态内容。但是,指向静态内容的URL也会通过自定义筛选器并且无法通过令牌验证。任何人都可以通过我的配置帮助搞清楚错误吗?
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private StatelessAuthenticationFilter statelessAuthenticationFilter;
@Autowired
private UserDetailsService userDetailsService;
public SpringSecurityConfig() {
super(true);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()
.anyRequest().authenticated().and()
// Custom Token based authentication based on the header
.addFilterBefore(statelessAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService());
}
@Override
public UserDetailsService userDetailsService() {
return userDetailsService;
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/auth");
}
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setEnabled(false);
filterRegistrationBean.setFilter(statelessAuthenticationFilter);
return filterRegistrationBean;
}
}
自定义过滤器:
@Component
public class StatelessAuthenticationFilter extends GenericFilterBean {
@Value("${security.token.secret:asdfasdfasdf}")
private String tokenSecret;
@Autowired
private UserRepository userRepository;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("stateless authentication filter");
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
try {
String token = httpRequest.getHeader(Constants.X_AUTH_TOKEN_HEADER_NAME);
if(!StringUtils.hasText(token)) {
throw new AuthenticationException(AirlineError.AUTHENTICATION_AUTH_TOKEN_MISSING);
}
JWTPayload jwtPayload = new JWTPayload();
byte[] secret = tokenSecret.getBytes();
DefaultJwtParser defaultJwtParser = new DefaultJwtParser();
defaultJwtParser.setSigningKey(secret);
Claims claims = defaultJwtParser.parseClaimsJws(token).getBody();
jwtPayload.setEmail((String) claims.get("email"));
jwtPayload.setExp((Long) claims.get("exp"));
if (new DateTime(jwtPayload.getExp()).isBeforeNow()) {
throw new AuthenticationException(AirlineError.AUTHENTICATION_AUTH_TOKEN_EXPIRED);
}
User user = userRepository.findOne(jwtPayload.getEmail());
SecurityContextHolder.getContext().setAuthentication(new UserAuthentication(user.getEmail()));
chain.doFilter(request, response);
} catch(Exception e) {
httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
}
}
index.html
位于/src/main/resources/static
文件夹中,但是当我从浏览器中打开http://localhost:8080时,它不会被提供。
编辑1 我在github中创建了一个示例项目来复制该问题。希望这会有所帮助:
https://github.com/mgooty/spring-boot-security
当我点击时:
An
Authentication object was not found in the SecurityContext
答案 0 :(得分:0)
如果您想允许对静态内容的所有访问,请在安全配置中对其进行配置:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()
.antMatchers("/index.html").permitAll()
.anyRequest().authenticated().and()
// Custom Token based authentication based on the header
.addFilterBefore(statelessAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
但是,由于自定义安全过滤器中的错误,这在您的情况下不起作用。但您仍然可以禁用index.html文件或其他静态资源的所有Web安全性(禁用所有过滤器)。
只需改变:
web.ignoring().antMatchers("/auth");
为:
web.ignoring().antMatchers("/auth", "/index.html");
请记住,您的应用将/src/main/resources/static
目录映射到/
个网址(资源网址中没有/static
前缀)。