问题描述
这是我当前的安全配置;如您所见,对于AntPathRequestMatcher
,我有一个/api/**
,应该为基于令牌的安全性应用一个过滤器。我的身份验证网址位于/api/token
下,显然不应受到保护。当前的.permitAll
似乎被忽略了;我该如何解决?
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private static final RequestMatcher PROTECTED_URLS = new OrRequestMatcher(
new AntPathRequestMatcher("/api/**")
);
private static final RequestMatcher FREE_URLS = new OrRequestMatcher(
new AntPathRequestMatcher("/api/token")
);
@Autowired
AuthenticationProvider provider;
public SecurityConfiguration(final AuthenticationProvider authenticationProvider) {
super();
this.provider = authenticationProvider;
}
@Override
protected void configure(final AuthenticationManagerBuilder auth) {
auth.authenticationProvider(provider);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.and()
.authorizeRequests()
.requestMatchers(FREE_URLS).permitAll()
.and()
.authenticationProvider(provider)
.addFilterBefore(authenticationFilter(),AnonymousAuthenticationFilter.class)
.authorizeRequests()
.requestMatchers(PROTECTED_URLS).authenticated()
.and()
.csrf().disable()
.formLogin().disable()
.httpBasic().disable()
.logout().disable();
}
@Bean
AuthenticationFilter authenticationFilter() throws Exception {
final AuthenticationFilter filter = new AuthenticationFilter(PROTECTED_URLS);
filter.setAuthenticationManager(authenticationManager());
return filter;
}
@Bean
AuthenticationEntryPoint forbiddenEntryPoint() {
return new HttpStatusEntryPoint(HttpStatus.FORBIDDEN);
}
}
编辑: 这是我的筛选器:可能确实是“抛出新的AuthenticationCredentialsNotFoundException”,但我不知道如何解决此问题。仅更改过滤器链配置是否不可能?过滤器仅适用于PROTECTED_URLS中列出的那些URL,但被FREE_URLS排除的URL除外。如果我要更改过滤器,那么是否不需要告诉过滤器免费URL?
public class AuthenticationFilter extends AbstractAuthenticationProcessingFilter {
AuthenticationFilter(final RequestMatcher requiresAuth) {
super(requiresAuth);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) throws AuthenticationException,IOException,servletexception {
String token= httpServletRequest.getHeader(AUTHORIZATION);
if(token==null) throw new AuthenticationCredentialsNotFoundException("Kein Token im Header angegeben");
token = StringUtils.removeStart(token,"Bearer").trim();
Authentication requestAuthentication = new UsernamePasswordAuthenticationToken(token,token);
return getAuthenticationManager().authenticate(requestAuthentication);
}
@Override
protected void successfulAuthentication(final HttpServletRequest request,final HttpServletResponse response,final FilterChain chain,final Authentication authResult) throws IOException,servletexception {
SecurityContextHolder.getContext().setAuthentication(authResult);
chain.doFilter(request,response);
}
}
解决方法
这可以通过以下方式解决:首先放置更具体的配置,使其首先匹配。
按如下所示更改您的配置方法:
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.and()
.authorizeRequests()
.requestMatchers(FREE_URLS).permitAll()
.and()
.authenticationProvider(provider)
.addFilterBefore(authenticationFilter(),AnonymousAuthenticationFilter.class)
.authorizeRequests()
.requestMatchers(FREE_URLS).permitAll()
.requestMatchers(PROTECTED_URLS).authenticated()
.and()
.csrf().disable()
.formLogin().disable()
.httpBasic().disable()
.logout().disable();