执行自定义过滤器 UsernamePasswordAuthenticationFilter 后如何以编程方式返回 json 响应?

Posted

技术标签:

【中文标题】执行自定义过滤器 UsernamePasswordAuthenticationFilter 后如何以编程方式返回 json 响应?【英文标题】:How to programatically return a json response after executing a custom filter UsernamePasswordAuthenticationFilter? 【发布时间】:2012-10-04 13:33:04 【问题描述】:

我正在创建一个自定义过滤器 UsernamePasswordAuthenticationFilter 来处理身份验证过程。基本上,当用户通过 REST /login 执行登录 http post 时,自定义过滤器将执行并应响应包含用户详细信息和生成令牌的 json 格式。

我的问题是我在哪里设置以响应客户端的 json 响应? 我正在考虑创建 SavedRequestAwareAuthenticationSuccessHandler 的子类并在那里设置 json 响应。这是个好主意吗?

任何帮助将不胜感激 =)

谢谢

【问题讨论】:

是否有理由实现自定义过滤器,而不是仅使用 spring 安全配置转发到生成所需 json 的 servlet? @mael:原因是要覆盖默认的 j_username/j_password 登录参数名称。所以我把它改成了用户名/密码。 无需为此实现自己的过滤器:The default parameter names to use are contained in the static fields SPRING_SECURITY_FORM_USERNAME_KEY and SPRING_SECURITY_FORM_PASSWORD_KEY. The parameter names can also be changed by setting the usernameParameter and passwordParameter properties. 感谢@Xaerxess,但这不是我最初的问题。问题出在我发布的那个=) @mael - 一个原因是 Ext-JS 在表单提交后期望返回 JSON,并且转发给它一个 html 文档。 【参考方案1】:

您需要实现自己的 SuccessHandler 并将其注入 UsernamePasswordAuthenticationFilter:

public class MyAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler 

   public MyAuthenticationSuccessHandler() 
       super();
       setRedirectStrategy(new NoRedirectStrategy());
   

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws IOException, ServletException 

           super.onAuthenticationSuccess(request, response, authentication);
           response.write("my JSON response");
    


    protected class NoRedirectStrategy implements RedirectStrategy 

        @Override
        public void sendRedirect(HttpServletRequest request,
                HttpServletResponse response, String url) throws IOException 
            // no redirect

        

    


注意 NoRedirectStrategy:默认情况下,用户名密码过滤器将在成功登录后重定向,在这种情况下您可能不希望这样做。另请注意,在上述实现中,过滤器链在身份验证成功时终止 - 您必须确保您的过滤器呈现正确的响应,不要依赖底层 servlet 为您完成。

或者,您可以保留重定向并将客户端发送到另一个 URL,该 URL 反过来呈现您正在寻找的 JSON 响应。

示例安全上下文:

    <!--  Security -->
    <bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
        <sec:filter-chain-map path-type="ant">
            <sec:filter-chain pattern="/rest/login" filters="wsFilter"/>
        </sec>
    </bean>

    <bean id="wsFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
      <property name="authenticationManager" ref="myAuthenticationManager"/>
      <property name="authenticationSuccessHandler" ref="myAuthSuccessHandler"/>
      <property name="passwordParameter" value="pass"></property>
      <property name="usernameParameter" value="user"></property>
      <property name="postOnly" value="false"></property>
   </bean>

       <bean id="myAuthSuccessHandler" class="com.my.MyAuthenticationSuccessHandler"/>

    <sec:authentication-manager id="myAuthenticationManager" >
        <sec:authentication-provider user-service-ref="UserDetailsImpl">
            <sec:password-encoder hash="md5">
            </sec:password-encoder>
        </sec:authentication-provider>
    </sec:authentication-manager>

【讨论】:

正文应该是response.getWriter().write(...)吗?

以上是关于执行自定义过滤器 UsernamePasswordAuthenticationFilter 后如何以编程方式返回 json 响应?的主要内容,如果未能解决你的问题,请参考以下文章

有啥方法或包我们可以在 django 中对自定义原始 sql 查询执行过滤器(搜索)?

MVC过滤器:自定义操作过滤器

MVC过滤器:自定义授权过滤器

如何在 Spring 身份验证管理器之前执行自定义处理程序

Django(自定义过滤器和自定义标签)

springboot怎么让自定义的拦截器优先于pagehelper执行