【问题标题】:Spring Security exclude url patterns in security annotation configurartionSpring Security 在安全注释配置中排除 url 模式
【发布时间】:2014-05-11 02:59:13
【问题描述】:

我有使用 java config 方法配置 Spring 安全性的 Spring Web 应用程序。我想从身份验证中排除一些 URL 模式(例如:静态资源等)。我之前已经使用 spring security xml config 完成了此操作,但无法通过 java config 弄清楚,因为添加 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 安全过滤器链中注册的过滤器,而它不应该因为请求被 antmatcher 忽略

【问题讨论】:

    标签: spring spring-mvc spring-security basic-authentication


    【解决方案1】:

    当您说添加 antMatchers 没有帮助时 - 您是什么意思? antMatchers 正是您这样做的方式。像下面这样的东西应该可以工作(显然适当地改变你的 URL):

    @Override
        public void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .antMatchers("/authFailure").permitAll()
                    .antMatchers("/resources/**").permitAll()
                    .anyRequest().authenticated()
    

    如果您仍然没有任何快乐,那么您将需要提供更多详细信息/堆栈跟踪等。

    Details of XML to Java config switch is here

    【讨论】:

    • 感谢您的回复,我已在问题中添加了堆栈跟踪。
    • @raj 看起来您有一个基于自定义令牌的安全过滤器?这是为了进一步安全检查吗?需要查看代码及其配置方式。
    • 我相信过滤器中的代码在这里无关紧要。即使删除了我的自定义过滤器,请求也会通过不应该的 Spring 安全过滤器堆栈。
    【解决方案2】:

    在 Github 上发布的 Spring 安全示例中找到了解决方案。

    WebSecurityConfigurerAdapter 有一个重载的configure 消息,该消息将WebSecurity 作为参数,它在请求被忽略时接受蚂蚁匹配器。

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/authFailure");
    }
    

    详情请见Spring Security Samples

    【讨论】:

    • 那个对我有用。谢谢!我能够添加所有被忽略的匹配项,例如登录表单、注销页面、静态资源等。然后将 .anyRequest.authenticated() 保留在我的 configure(HttpSecurity http) 方法中。
    • 就标准而言,覆盖配置(WebSecurity)似乎是正确的。 stackoverflow.com/questions/22998731/…
    • 为什么用这个代替.permitAll()
    • @mad_fox "尝试验证访问此资源并允许所有人访问的用户" (permitAll()) vs "甚至不要尝试验证访问此资源的用户"
    • 区别如下。我有一个项目,它有一个每个人都可以访问的休息端点。它是/api/model/all。我已将该 URL 的 httpsecurity 设置为 permitAll。我发送了一个授权令牌,如果令牌已过期,即使不需要身份验证,其余调用也会失败。通过使用 WebSecurity 并将 url 添加到忽略列表,然后您表明即使您发送身份验证也只是忽略 if 并调用端点。因此,Websecurity 用于禁用安全检查,而 permitAll 用于在验证用户身份后允许所有访问。
    【解决方案3】:

    您在哪里配置经过身份验证的 URL 模式?我在您的代码中只看到一个 uri。

    您有多个 configure(HttpSecurity) 方法还是只有一个?看起来您需要一种方法中的所有 URI。

    我有一个需要身份验证才能访问所有内容的网站,所以我想保护 /*.但是,为了进行身份验证,我显然不想保护 /login。我还有一些我想允许访问的静态资产(这样我就可以使登录页面变得漂亮)和一个不需要身份验证的健康检查页面。

    此外,我还有一个资源 /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”可以访问管理界面(哎呀!)

    【讨论】:

      【解决方案4】:

      在“authorizeRequests()”之前指定“antMatcher”,如下所示,将仅对“antMatcher”中指定的 URL 进行身份验证

      http.csrf().disable() .antMatcher("/apiurlneedsauth/**").authorizeRequests().

      【讨论】:

      • 对我来说也可以在没有前置条件的“authorizeRequests()”模式之前工作:http.antMatcher("!/apiurlNotNeedAuth/**")
      猜你喜欢
      • 2011-09-07
      • 1970-01-01
      • 2013-10-21
      • 2022-10-19
      • 1970-01-01
      • 1970-01-01
      • 2012-03-03
      • 2012-01-04
      • 2016-03-16
      相关资源
      最近更新 更多