如何在Spring Security中编写自定义过滤器?

52
我希望通过请求获得一些信息,所以我认为,与其为每个请求编写一个函数并单独从请求中获取这些信息,最好使用过滤器。
因此,每个请求都必须通过该过滤器,然后我就得到我想要的信息。

问题是:如何编写自定义过滤器?
假设它不像任何预定义的Spring安全过滤器,而是完全新的。
2个回答

49

您可以使用标准的Java过滤器。只需在web.xml中的身份验证过滤器之后放置它(这意味着它将在过滤器链中稍后调用,并且会在安全性过滤器链之后被调用)。

public class CustomFilter implements Filter{

    @Override
    public void destroy() {
        // Do nothing
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res,
            FilterChain chain) throws IOException, ServletException {

            HttpServletRequest request = (HttpServletRequest) req;

            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

            Set<String> roles = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
            if (roles.contains("ROLE_USER")) {
                request.getSession().setAttribute("myVale", "myvalue");
            }

            chain.doFilter(req, res);

    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // Do nothing
    }

}

web.xml 的片段:

<!-- The Spring Security Filter Chain -->
<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>

<!-- Your filter definition -->
<filter>
    <filter-name>customFilter</filter-name>
    <filter-class>com.yourcompany.test.CustomFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>customFilter</filter-name>
    <url-pattern>/VacationsManager.jsp</url-pattern>
</filter-mapping>

还可以添加处理程序,在成功登录后调用该处理程序(需要扩展SavedRequestAwareAuthenticationSuccessHandler)。在这里查看如何操作。我认为这是一个更好的想法。


更新:
或者你可以将这个过滤器放在安全过滤器的末尾,像这样:

<security:filter-chain-map>
    <sec:filter-chain pattern="/**"
            filters="
        ConcurrentSessionFilterAdmin, 
        securityContextPersistenceFilter, 
        logoutFilterAdmin, 
        usernamePasswordAuthenticationFilterAdmin, 
        basicAuthenticationFilterAdmin, 
        requestCacheAwareFilter, 
        securityContextHolderAwareRequestFilter, 
        anonymousAuthenticationFilter, 
        sessionManagementFilterAdmin, 
        exceptionTranslationFilter, 
        filterSecurityInterceptorAdmin,
        MonitoringFilter"/> <!-- Your Filter at the End -->
</security:filter-chain-map>

如果你想要使用筛选器,你可以使用以下方法:

public class MonitoringFilter extends GenericFilterBean{
@Override
public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException {
    //Implement this Function to have your filter working
}

当我在等待答案时,我想出了一个解决方案。我在我的安全过滤器的末尾添加了我的过滤器(扩展了GenericFilterBean)。它运行得很好。但是现在,当我看到你的答案时,它听起来更好。我会尝试你的解决方案。希望它也能正常工作。我会告诉你结果的。谢谢。 - Matin Kh
通常您的回答是正确的,但我必须稍微修改一下。感谢您的帮助。 - Matin Kh
5
是的,你的解决方案也不错。但在这种情况下,我们需要定义所有过滤器(包括默认值),如果有遗漏,它将不会被调用。我说得对吗? - dimas
能否将JPA存储库自动装配到此自定义过滤器中? - Tayba
1
“标准Java过滤器”是什么意思?javax.servlet.Filter是指什么? - Andrew Tobilko
显示剩余3条评论

15

仅供参考;在http元素内部使用custom-filter,如何?

<security:http auto-config="false" ...>
  ...
  <security:custom-filter position="FORM_LOGIN_FILTER" ref="MyCustomFilter" />
</security:http>

1
这绝对是最好的解决方案。我想在所有其他操作之前运行自己的过滤器:<custom-filter ref="myCustomFilter" before="FIRST"/> - John Mikic
我可以在<security:custom-filter position="FORM_LOGIN_FILTER" ref="MyCustomFilter" />中添加模式吗? - Ram Chhabra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接