有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java定制Spring过滤器导致链中的下一个过滤器不启动?

我使用的是一个定制的Spring安全过滤器,它覆盖AbstractAuthenticationProcessingFilter,但我一定写错了,因为它似乎从未调用过滤器链的其余部分。具体来说,我依靠OpenEntityManagerInViewFilter过滤器来确保Jackson+Hibernate可以处理延迟加载的对象

如果我的网站。xml有OpenEntityManagerViewFilter首先,一切正常:

<filter>
    <filter-name>hibernateFilterChain</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>hibernateFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<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>
</filter-mapping>

但是,如果我将springSecurityFilterChain放在顶部,我的应用程序的行为就好像我根本没有指定OpenEntityManagerViewFilter一样

这是我的安全措施。xml:

<?xml version="1.0"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.2.xsd">

<security:http entry-point-ref="restAuthenticationEntryPoint"
    use-expressions="true" create-session="stateless">

    <security:custom-filter ref="authenticationTokenProcessingFilter"
        position="FORM_LOGIN_FILTER" />
    <security:intercept-url pattern="/**"
        access="isAuthenticated()" />

    <security:logout />
</security:http>

<bean class="edu.ucdavis.dss.dw.security.CustomTokenAuthenticationFilter"
    id="authenticationTokenProcessingFilter">
    <constructor-arg type="java.lang.String">
        <value>/**</value>
    </constructor-arg>
</bean>

<security:authentication-manager>
    <security:authentication-provider
        user-service-ref="userService"></security:authentication-provider>
</security:authentication-manager>

<bean id="userService" class="edu.ucdavis.dss.dw.services.UserAuthenticationService"></bean>

</beans>

最后,这里是CustomTokenAuthenticationFilter本身,这可能会导致问题:

public class CustomTokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
    @Autowired @Qualifier("org.springframework.security.authenticationManager")
    private AuthenticationManager authenticationManager;

    public CustomTokenAuthenticationFilter(String defaultFilterProcessesUrl) {
        super(defaultFilterProcessesUrl);
        super.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(defaultFilterProcessesUrl));
        setAuthenticationManager(new NoOpAuthenticationManager());
        setAuthenticationSuccessHandler(new TokenSimpleUrlAuthenticationSuccessHandler());
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        String token = request.getParameter("token");

        if(token == null) {
            throw new AuthenticationServiceException("Token Missing");
        }

        Authentication authResponse;

        try {
            authResponse = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(token, "dssit"));
        } catch (AuthenticationException e) {
            throw new AuthenticationServiceException("Bad Token");
        }

        return authResponse;
    }
}

总结:我做了一个自定义的安全过滤器,它似乎没有调用后面列出的任何过滤器。如果我删除我的自定义过滤器并使用一些内置的东西,比如安全性:http basic,它就可以正常工作

提前感谢您提供的任何帮助


共 (3) 个答案

  1. # 1 楼答案

    据我所知,Spring身份验证过滤器旨在对请求进行身份验证,然后重定向到某个地方,启动一个全新的请求。这意味着过滤器链被故意停止。其思想是,一旦经过身份验证,并且在新请求中,身份验证会话将已经存在,这样身份验证过滤器就不必再次重定向。至少,这是我从一点调试中得到的理解

    为了避免这种行为,您必须实现自己的AbstractAuthenticationProcessingFilter、AuthenticationEntryPoint、AbstractAuthenticationToken、AuthenticationProvider和SimpleRuthenticationSuccessHandler

  2. # 2 楼答案

    AbstractAuthenticationProcessingFilter类具有以下可重写的方法:

    protected boolean requiresAuthentication(HttpServletRequest request,
            HttpServletResponse response)
    

    在使用筛选器启动身份验证之前调用此方法(在doFilter):

    if (!requiresAuthentication(request, response)) {
        chain.doFilter(request, response);
    
        return;
    }
    

    子类应该重写这个方法,以检查它是否可以对请求进行身份验证:如果令牌不存在或无效,它应该返回false

    例如:

    @Override
    protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
    
        if (!super.requiresAuthentication(request, response)) {
           // We're not required to authenticate this request (ant matchers).
           return false;
        }
    
        if (null == request.getParameter("token")) {
           // We can't authenticate this request, because the token is missing.
           return false;
        }
    
        try {
          authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(token, "dssit"));
        } catch (AuthenticationException e) {
          // We can't authenticate this token because an exception occurred.
          return false;
        }
    
        // We can authenticate this request.
        return true;
    }
    
  3. # 3 楼答案

    是否要尝试添加

    public void doFilter(javax.servlet.ServletRequest req,
            javax.servlet.ServletResponse res,
            javax.servlet.FilterChain chain)
              throws IOException,
                     javax.servlet.ServletException {
    
        chain.doFilter(req, res);
    }
    

    到CustomTokenAuthenticationFilter类