我有一个 Spring Web 应用程序,使用 java 配置方法配置了 Spring security。我想从身份验证中排除一些 URL 模式(例如:静态资源等..)。我之前已经使用 spring security xml 配置完成了此操作,但无法使用 java 配置来弄清楚,因为添加 antmatchers 没有帮助。以下是我在安全配置类中添加的代码,扩展了
WebSecurityConfigurerAdapter
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/authFailure")
.permitAll()
.anyRequest()
.authenticated()
.and()
.httpBasic()
.and()
.authenticationProvider(_provider)
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilter(authFilter())
.addFilterAfter(executionContextFilter(),
TokenBasedSecurityFilter.class).csrf().disable();
}
我使用的Spring Security版本是3.2.0。
编辑:
我在点击排除的 URL 时获得的堆栈跟踪,
org.springframework.security.authentication.AuthenticationServiceException: Authorization Header is not available in the request
at com.inventory.ricemill.tba.spring.TokenBasedSecurityFilter.doFilter(TokenBasedSecurityFilter.java:59)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Apr 01, 2014 10:18:41 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Inventory] in context with path [/ricemill] threw exception [Request processing failed; nested exception is org.springframework.security.authentication.AuthenticationServiceException: Authorization Header is not available in the request] with root cause
org.springframework.security.authentication.AuthenticationServiceException: Authorization Header is not available in the request
at com.inventory.ricemill.tba.spring.TokenBasedSecurityFilter.doFilter(TokenBasedSecurityFilter.java:59)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
请求通过在 Spring Security 过滤器链中注册的过滤器,但它不应该通过,因为 antmatcher 会忽略该请求
在 Github 上发布的 Spring 安全示例中找到了解决方案。
WebSecurityConfigurerAdapter
有一个重载的 configure
消息,它以 WebSecurity
作为参数,接受要忽略的请求上的 ant 匹配器。
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/authFailure");
}
请参阅 Spring Security 示例了解更多详细信息
您在哪里配置经过身份验证的 URL 模式?我在你的代码中只看到一个 uri。
您有多个配置(HttpSecurity)方法还是只有一个?看起来您需要在一个方法中使用所有 URI。
我有一个需要身份验证才能访问所有内容的网站,因此我想保护 /*。然而,为了进行身份验证,我显然不想保护/登录。我还希望允许访问静态资产(这样我可以使登录页面变得漂亮)和不需要身份验证的运行状况检查页面。
此外,我有一个资源 /admin,它需要比网站其他部分更高的权限。
以下对我有用。
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login**").permitAll()
.antMatchers("/healthcheck**").permitAll()
.antMatchers("/static/**").permitAll()
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
.antMatchers("/**").access("hasRole('ROLE_USER')")
.and()
.formLogin().loginPage("/login").failureUrl("/login?error")
.usernameParameter("username").passwordParameter("password")
.and()
.logout().logoutSuccessUrl("/login?logout")
.and()
.exceptionHandling().accessDeniedPage("/403")
.and()
.csrf();
}
注意:这是第一场比赛获胜,因此您可能需要按照顺序进行比赛。 例如,我最初有 /** 首先:
.antMatchers("/**").access("hasRole('ROLE_USER')")
.antMatchers("/login**").permitAll()
.antMatchers("/healthcheck**").permitAll()
这导致网站不断将所有 /login 请求重定向回 /login。同样,我最后有/admin/**:
.antMatchers("/**").access("hasRole('ROLE_USER')")
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
这导致我的非特权测试用户“guest”可以访问管理界面(哎呀!)
当您说添加 antMatchers 没有帮助时 - 您的意思是什么? antMatchers 正是您的做法。像下面这样的东西应该可以工作(显然适当地改变你的URL):
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/authFailure").permitAll()
.antMatchers("/resources/**").permitAll()
.anyRequest().authenticated()
如果您仍然没有任何乐趣,那么您将需要提供更多详细信息/堆栈跟踪等。
对此处已给出的答案的补充。
对于身份验证和授权之间的区别,似乎有很多混淆。
Spring Security 先执行身份验证,然后才执行授权,这是有道理的。
这意味着它将首先执行身份验证过滤器,然后才验证授权端点。
要规避自定义身份验证过滤器,
permitAll
将不起作用,因为这涉及授权,并且NOT身份验证。WebSecurityConfigurerAdapter
。 @Bean
public WebSecurityCustomizer ignoringCustomizer() {
return (web) -> web.ignoring().requestMatchers("/ignore1", "/ignore2");
}
或者使用 antMatchers。
在“authorizeRequests()”之前指定“antMatcher”,如下所示,会将身份验证限制为仅在“antMatcher”中指定的那些 URL
http.csrf().disable() .antMatcher("/apiurlneedsauth/**").authorizeRequests().
以更现代的方式,它应该看起来像:
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring().antMatchers("/authFailure");
}
我发现上面所有的解决方案已经过时了... 这就是我最终得到的解决方案
@Configuration
@EnableWebSecurity/*(debug = true)*/
@RequiredArgsConstructor
@EnableMethodSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// @formatter:off
return http
.csrf()
.disable()
.headers().frameOptions().disable()
.and()
// Enable CORS at Spring Security level
.cors()
.and()
.authorizeHttpRequests()
.requestMatchers("/login/**", "/api/noAuth/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(new CustomJwtAuthenticationConverter(new UserDetailsConverter()))
.and()
.and().build();
// @formatter:on
}
}
对于 SpringBoot 版本 6,请考虑在配置中定义一个 bean,并添加您想要忽略安全检查的 url。
@Bean
公共 WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring().requestMatchers("/yourUrlToIgnore","/secondurl"...);
}
有关更多详细信息,请检查此,https://spring.io/blog/2022/02/21/spring-security-without-the-websecurityconfigureradapter