登录失败时我想将用户重定向到错误页面并显示有意义的错误消息。是否可以添加将传递给后续请求的Flash属性?
下面提供的代码不起作用。 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");
}
}
答案 0 :(得分:2)
我在Spring 4.3.17中遇到了同样的问题,最后通过spring-webmvc代码找到了一个解决方案,并对如何在常规框架之外集成Flash属性进行了有根据的猜测。 SessionFlashMapManager是实现此目标的关键。我相信这个方法适用于Spring 3.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>
答案 1 :(得分:1)
我猜它是空的,因为你是从过滤器链调用函数,而flash映射是由Spring的DispatcherServlet
维护的,此时请求还没有通过。
为什么不使用参数?即
response.sendRedirect(request.getContextPath()+"/error?error=" + "Error Message");