【问题标题】:Why filter chain is never called?为什么过滤器链永远不会被调用?
【发布时间】:2017-04-16 00:07:11
【问题描述】:

我目前正在开发一个可从应用程序池访问的网络应用程序。基本上,这个池为每个应用程序提供一组链接,传递一个标识先前登录用户的密钥。

有问题的应用程序应该使用给定的令牌(可能来自任何请求 url)授权用户,将用户存储到 spring 安全上下文中并处理控制器。碰巧没有调用弹簧安全过滤器,控制器返回500而不是403

我尝试了一些东西,最终将自定义入口点转发到自定义 UsernamePasswordAuthenticationFilter 以检索用户,然后自定义 AuthenticationProvider 应该授权检索的用户,但我很确定这不是最好的方法.

SecurityConfig.java

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private SwgenAuthFilter swgenAuthFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.httpBasic()
            .and()
                .authorizeRequests()
                .anyRequest()
                .authenticated()
            .and()
                .exceptionHandling()
                .accessDeniedPage("/403")
                .authenticationEntryPoint(new SwgenEntryPoint())
            .and()
                .addFilter(swgenAuthFilter);
    }

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

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return new ProviderManager(Arrays.asList(new SwgenAuthProvider()));
    }

}

SwgenEntryPoint.java

public class SwgenEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
            throws IOException, ServletException {
        RequestDispatcher dispatcher = request.getRequestDispatcher("/login");

        dispatcher.forward(request, response);

        return;
    }

}

SwgenAuthFilter.java

@Component
public class SwgenAuthFilter extends UsernamePasswordAuthenticationFilter {

    @Autowired
    private SecurityProvider securityProvider;

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        try {
            User user = securityProvider.getUser(request, response);
            return new UsernamePasswordAuthenticationToken(user, null);
        } catch (Exception e) {
            throw new AuthenticationServiceException("Eccezione scatenata durante l'autenticazione", e);
        }
    }

    @Override
    @Autowired
    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
        super.setAuthenticationManager(authenticationManager);
    }

}

HomeController.java

@Controller
public class HomeController {

    static final private Logger logger = Logger.getLogger(HomeController.class);

    @Secured({Role.ADMIN, Role.REGIONE})
    @RequestMapping(value = "/home")
    public String home(Model model, HttpServletRequest request) {
        // get user from SpringContextHolder
        User utente = Utils.getUser();

        if(utente != null) {
            logger.info("User correctly authenticated")
        }

        return "home";
    }
}

堆栈跟踪

2016-12-01 12::03:07.343 DEBUG [org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor] Secure object: ReflectiveMethodInvocation: public java.lang.String it.regioneveneto.sanita.progettobase.controller.HomeController.home(org.springframework.ui.Model,javax.servlet.http.HttpServletRequest); target is of class [it.regioneveneto.sanita.progettobase.controller.HomeController]; Attributes: [ROLE_MRA_ADMIN, ROLE_MRA_REGIONE, ROLE_MRA_ULSS]
dic 01, 2016 12:03:07 PM org.apache.catalina.core.StandardWrapperValve invoke
GRAVE: Servlet.service() for servlet [dispatcher] in context with path [/mra_auac] threw exception [Request processing failed; nested exception is org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext] with root cause
org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:379)
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:223)
    at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:65)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655)
    at it.regioneveneto.sanita.progettobase.controller.HomeController$$EnhancerBySpringCGLIB$$8c44d861.home(<generated>)
    ...

Spring mvc:4.3.4.RELEASE

Spring 安全性:4.2.0.RELEASE

编辑:

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

    <display-name>mra_auac</display-name>
    <description>MRA-AuAc</description>

    <context-param>
        <param-name>contextClass</param-name>
        <param-value>
            org.springframework.web.context.support.AnnotationConfigWebApplicationContext
        </param-value>
    </context-param>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>it.regioneveneto.sanita.progettobase.configuration.AppConfig</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
        </init-param>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                it.regioneveneto.sanita.progettobase.configuration.HibernateConfig,
                it.regioneveneto.sanita.progettobase.configuration.security.SecurityConfig
            </param-value>
        </init-param>
        <multipart-config>
            <max-file-size>20971520</max-file-size><!--20MB -->
            <max-request-size>20971520</max-request-size><!--20MB -->
            <file-size-threshold>0</file-size-threshold>
        </multipart-config>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <error-page>
        <error-code>404</error-code>
        <location>/404.htm</location>
    </error-page>
    <error-page>
        <error-code>500</error-code>
        <location>/500.htm</location>
    </error-page>

    <session-config>
        <session-timeout>60</session-timeout>
    </session-config>

</web-app>

【问题讨论】:

    标签: java spring spring-security


    【解决方案1】:

    shazin 指出您的web.xml 错过了对springSecurityFilterChain 的引用。您可以按照Spring Documentation 中报告的方式使用 xml 格式进行操作:

    <filter>
      <filter-name>springSecurityFilterChain</filter-name>
      <filter-class>
        org.springframework.web.filter.DelegatingFilterProxy
      </filter-class>
    </filter>
    
    <filter-mapping>
      <filter-name>springSecurityFilterChain</filter-name>
      <url-pattern>/*</url-pattern>
      <dispatcher>ERROR</dispatcher>
      <dispatcher>REQUEST</dispatcher>
    </filter-mapping>
    

    在您的项目中包含一个扩展 AbstractSecurityWebApplicationInitializer 的类,如下所示:

    public class SecurityWebApplicationInitializer 
       extends AbstractSecurityWebApplicationInitializer {}
    

    如果您想从web.xml 中删除一些代码,您可以通过替换

    轻松做到这一点
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            it.regioneveneto.sanita.progettobase.configuration.HibernateConfig,
            it.regioneveneto.sanita.progettobase.configuration.security.SecurityConfig
        </param-value>
    </init-param>
    

    用:AppConfig 注释类:

    @Import({ SecurityConfig.class, HibernateConfig.class }) //remember to import them
    

    【讨论】:

      【解决方案2】:

      您的 web.xml 没有指定 springSecurityFilterChain 过滤器。

      <filter>
          <filter-name>springSecurityFilterChain</filter-name>
          <filter-class>org.springframework.web.filter.DelegatingProxyFilter</filter-class>
      </filter>
      
      <filter-mapping>
          <filter-name>springSecurityFilterChain</filter-name>
          <url-pattern>/</url-pattern>
      </filter-mapping>
      

      【讨论】:

      • 这解决了问题,但是在另一个项目中,使用 Spring 4.2.5.RELEASE 和 Spring Security 4.0.4.RELEASE 和相同的配置,我不需要在 web.xml 中添加 springSecurityFilterChain。发生了什么变化?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-22
      • 2018-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-06
      相关资源
      最近更新 更多