我正在尝试在登录失败时重定向登录页面上输入的用户名,但在我的控制器中,从“@ModelAttribute(”user“)”检索到的用户的用户名为空 . 当我不使用 spring 安全时,这是有效的 .
我假设表格实际上首先弹出安全性,然后将其重定向到控制器,因此输入的信息在spring security之间丢失 .
如何在不将其发送到链接参数的情况下检索用户?
PS:我试图为“/ loginFailed”创建一个控制器,并在登录失败时将其发送到那里并在该控制器上使用method = RequestMethod.POST .
的LoginController
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String listPersons(@ModelAttribute("user") User u, @RequestParam(required = false) String authfailed, String logout,
String denied, Model model) {
model.addAttribute("user", u);
String message = "";
if (authfailed != null) {
message = "Invalid username or password, try again !";
} else if (logout != null) {
message = "Logged Out successfully, login again to continue !";
} else if (denied != null) {
message = "Access denied for this user !";
}
model.addAttribute("error", message);
return "login";
}
login.jsp的
<c:url var="trylogin" value="/j_spring_security_check" ></c:url>
<c:url var="register" value="/register" ></c:url>
<div id="login-box">
<form:form action="" modelAttribute="user" method="POST">
<table>
<tr>
<td> <form:label path="username"> <spring:message text="Username: "/> </form:label> </td>
<td> <form:input path="username" /> </td>
</tr>
<tr>
<td> <form:label path="password"> <spring:message text="Password: "/> </form:label> </td>
<td> <form:password path="password" /> </td>
</tr>
<tr>
<td> <input type="submit" value="<spring:message text="Login"/>"
onclick="document.getElementById('user').setAttribute('action', '${trylogin}')"/> </td>
<td> <input type="submit" value="<spring:message text="Register"/>"
onclick="document.getElementById('user').setAttribute('action', '${register}')"/> </td>
</tr>
</table>
</form:form>
<c:if test="${not empty error}">
<div class="error">${error}</div>
</c:if>
</div>
编辑(解决方案):
谢谢你@James创建一个失败的手是方法,但你的解决方案没有完全正常工作,因为看起来你在failureHandler bean中需要“p:defaultFailureUrl”,即使我有“authentication-failure-url =”/ login?在表单登录中使用authfailed“”
<bean id="failureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"
p:useForward="true"
p:defaultFailureUrl="/login"/>
之后我必须使用方法发布为/ login添加另一个函数,因为p:defaultFailureUrl =“/ login?authFailed”将它发送为/ login并且浏览器中的链接保持为“/ j_spring_security_check”我无法理解为什么 .
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String loginFail(@ModelAttribute("user") User u, @RequestParam(required = false) String authfailed, RedirectAttributes redirectAttrs) {
redirectAttrs.addFlashAttribute("user", u);
redirectAttrs.addFlashAttribute("error", "Invalid username or password, try again !");
return "redirect:/login";
}
2 回答
您应该使用AuthenticationFailureHandler . 为了您的目的,它应该足以声明Spring SimpleUrlAuthenticationFailureHandler类的bean,并指定将请求发送到目标URL而不是配置中的默认重定向行为 . 这样您的登录控制器就可以访问原始请求,包括用户名 .
文件:http://docs.spring.io/autorepo/docs/spring-security/3.2.1.RELEASE/apidocs/org/springframework/security/web/authentication/SimpleUrlAuthenticationFailureHandler.html
资料来源:https://github.com/spring-projects/spring-security/blob/master/web/src/main/java/org/springframework/security/web/authentication/SimpleUrlAuthenticationFailureHandler.java
然后在您的表单登录规范中:
这是一种错误的方式 . 登录页面控制器仅用于查看此页面 . 对于检查凭证,您需要创建服务,例如:
使用spring分配此服务(例如,我为了安全性而查看我的简单配置):
然后当用户提交登录表单时,我们会重定向到使用我们服务的/ j_spring_security_check,如果我们有登录异常,我们可以在登录jsp页面检查它:
如果成功,我们将重定向到默认目标网址,在我的情况下,重定向到root .
这就是浏览器链接保持为“/ j_spring_security_check”的原因 .