如何解决两个匹配器都适合,如何避免应用过滤器?
这是我当前的安全配置;如您所见,对于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();
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。