Spring 自定义AuthenticationFailureHandler中的Flash属性

Spring 自定义AuthenticationFailureHandler中的Flash属性,spring,authentication,spring-security,Spring,Authentication,Spring Security,登录失败时,我想将用户重定向到错误页面,并显示有意义的错误消息。是否可以添加将传递给后续请求的闪存属性 下面给出的代码不起作用RequestContextUtils.getOutputFlashMap()返回null public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler { @Override public void onAuthenticationFailu

登录失败时,我想将用户重定向到错误页面,并显示有意义的错误消息。是否可以添加将传递给后续请求的闪存属性

下面给出的代码不起作用
RequestContextUtils.getOutputFlashMap()
返回
null

public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler
{
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException
    {
        FlashMap outputFlashMap = RequestContextUtils.getOutputFlashMap(request);
        if (outputFlashMap != null)
        {
            outputFlashMap.put("error", "Error message");
        }
        response.sendRedirect(request.getContextPath() + "/error");
    }
}

我猜它是空的,因为您是从过滤器链调用函数的,而flash映射是由Spring的
DispatcherServlet
维护的,此时请求还没有通过它

为什么不使用一个参数呢?i、 e

 response.sendRedirect(request.getContextPath()+"/error?error=" + "Error Message");

我在Spring4.3.17中遇到了同样的问题,最终通过逐步阅读SpringWebMVC代码并对如何在正常框架之外集成Flash属性进行有根据的猜测,找到了一个解决方案。这是让它发挥作用的关键。我相信这种方法应该适用于Spring3.1.1+

package org.myorg.spring.security;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.FlashMap;
import org.springframework.web.servlet.FlashMapManager;
import org.springframework.web.servlet.support.SessionFlashMapManager;

@Component
public final class FlashAuthenticationFailureHandler implements AuthenticationFailureHandler
{
    /**
     * Flash attribute name to save on redirect.
     */
    public static final String AUTHENTICATION_MESSAGE = "FLASH_AUTHENTICATION_MESSAGE";

    public FlashAuthenticationFailureHandler()
    {
        return;
    }

    @Override
    public void onAuthenticationFailure(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException exception) throws IOException, ServletException
    {
        if (exception != null)
        {
            final FlashMap flashMap = new FlashMap();
            // Don't send the AuthenticationException object itself because it has no default constructor and cannot be re-instantiated.
            flashMap.put(AUTHENTICATION_MESSAGE, exception.getMessage());
            final FlashMapManager flashMapManager = new SessionFlashMapManager();
            flashMapManager.saveOutputFlashMap(flashMap, request, response);
        }
        response.sendRedirect(request.getHeader("referer"));
        return;
    }
}
然后在需要flash属性的控制器中,只需添加一个同名的ModelAttribute:

@RequestMapping(value = {"/someview"}, method = RequestMethod.GET)
public String getSomePage(final Authentication authentication, @ModelAttribute(FlashAuthenticationFailureHandler.AUTHENTICATION_MESSAGE) final String authenticationMessage, final Model model) throws Exception
{
    if (authenticationMessage != null)
    {
        model.addAttribute("loginMessage", authenticationMessage);
    }

    return "myviewname";
}
然后可以在JSP中访问包含消息的页面属性,如下所示:

<c:if test="${not empty loginMessage}">
  <div class="alert alert-danger"><c:out value="${loginMessage}" /></div>
</c:if>

若并没有其他选项,这是可行的,但我不希望在查询字符串中透露我的参数。