【发布时间】:2020-12-05 16:49:58
【问题描述】:
这是我当前的安全配置;如您所见,我为/api/** 提供了一个AntPathRequestMatcher,它应该为基于令牌的安全性应用过滤器;我的身份验证 URL 位于 /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);
}
}
【问题讨论】:
-
您第二次调用
.authorizeRequests()会覆盖第一次调用。 -
如果我正确理解链接的帖子,那与我的问题不一样;在我的情况下,所有 SECURED_URLS (A) 路径都是安全的,但 FREE_URLS (B) 除外,但集合 B 仍然是集合 A 的一部分。
-
不,你没有正确理解。一个问题是您使用了两次
authorizeRequests。这根本没有意义。 -
new AuthenticationFilter(PROTECTED_URLS)应该只对受保护的 URL 应用过滤器,但/api/**包含/api/token。因此,您的过滤器也适用于免费 URL。您必须排除免费 URL。 -
您的意思是从受保护的 URL 中排除 URL?所以我必须将受保护的 URL 定义为包含 {"/api/path1/**","/api/path2/**","/api/path3/**"} 而不是 "/api/token" ?
标签: spring spring-boot security spring-security