Spring Security:如何在另一个模块的安全调用之前添加过滤控件

时间:2017-04-06 09:12:26

标签: spring security filter

我有一个带有安全授权实现的J2EE应用程序,作为第一步,它调用安全授权操作的依赖项。 在此依赖性模块中,已检查访问令牌是否为空:如果是,则抛出NullPointerException。 我需要在我的应用程序中捕获此异常,以便重定向到jsp自定义页面而不是500错误页面。

关键是我从未通过我的一个app类,所以我无法捕获异常,因为不是我的应用程序直接调用另一个:链由Spring Security机制处理。 从堆栈跟踪中我看到我在 LogoutFilter 上传递了 DelegatingFilterProxy ,然后传递到 SecurityContextPersistenceFilter 上的 FilterChainProxy 此时,控件将传递依赖项应用程序,其中抛出异常。

我是否可以在令牌字符串上添加预防性控制,以便在调用依赖项以确保安全性之前控制重定向?

这是允许Spring调用依赖过滤器(preAuthenticationFilter)作为第一步的Spring配置:

<http auto-config="true" access-denied-page="/500" use-expressions="true">
    <custom-filter position="PRE_AUTH_FILTER" ref="preAuthenticationFilter" />
    <intercept-url pattern="/portal/**" access="isAuthenticated()" />
    <intercept-url pattern="/**" access="permitAll" />

    <logout logout-url="/logout" delete-cookies="true"
        invalidate-session="true" logout-success-url="/logoutsuccess" />

    <session-management session-fixation-protection="newSession" />
</http>

编辑:这是修改bean配置以定义FilterWrapper:

<bean id="preAuthenticationFilter" class="com.example.FilterWrapper">
    <constructor-arg>
        <bean class="com.example.MyPreAuthenticationFilter" >
            <property name="authenticationManager" ref="authenticationManager" />
            <property name="continueFilterChainOnUnsuccessfulAuthentication" value="false" />
            <property name="verifyTokenChanged" value="true" />
        </bean>
    </constructor-arg>
</beans:bean>

1 个答案:

答案 0 :(得分:1)

显然应该修复自定义过滤器,以便它不会抛出NullPointerException。从你的帖子我发现这个过滤器的代码可能不在你的控制之下,但它似乎是在你的Spring上下文中初始化的,这意味着你总是可以为它捕获异常创建一个包装器,例如:< / p>

public class FilterWrapper extends OncePerRequestFilter {
  private final Filter target;

  public FilterWrapper(Filter target) {
     this.target = target;
  }

  @Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    try {
      target.doFilter(request, response, filterChain);
    } catch(NullPointerException e) {
       response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication token is required");
    }
  }
}

现在,更改preAuthenticationFilter的bean定义,使用原始过滤器周围的包装器,你应该没问题。

配置文件中的某处应该有一个像这样的bean定义:

<bean class="com.example.MyPreAuthenticationFilter" id="preAuthenticationFilter" />

将该定义更改为:

<bean class="com.example.FilterWrapper" id="preAuthenticationFilter">
  <constructor-arg>
    <bean class="com.example.MyPreAuthenticationFilter" />
  </constructor-arg>
</bean>