您可以使用SavedRequestAwareAuthenticationSuccessHandler。
当一个非授权请求到达ExceptionTranslationFilter时,会创建一个HttpSessionRequestCache类的RequestCache,并将原始请求保存在上面。
这样,如果您不将alwaysUseDefaultTargetUrl 设置为true,httpRequest 将被重构并用作目标url,同时执行正确的登录。
所以,尝试 @Autowire(我使用 @Resource 代替,因为我的安全配置中有多个 AuthenticationManager 和 AuthenticationSuccessHandler)控制器中的 AuthenticationSuccessHandler 并像这样调用 determineTargetUrl():
我做了一些修改,例如使用@Valid 注释并实现Validator 来验证注册表单
安全性.xml
<beans:bean id="savedRequestSuccesHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<beans:property name="defaultTargetUrl" value="/zone4/secured/securedPage.htm" />
</beans:bean>
<security:http pattern="/zone4/**" use-expressions="true" authentication-manager-ref="mainAuthenticationManager">
<security:intercept-url pattern="/zone4/simple/**" access="permitAll()" />
<security:intercept-url pattern="/zone4/secured/**" access="isAuthenticated()"/>
<security:form-login
login-page="/zone4/simple/login.htm"
authentication-failure-url="/login.htm?error=true"
authentication-success-handler-ref="savedRequestSuccesHandler"
username-parameter="email"
password-parameter="password"
login-processing-url="/zone4/secured/performLogin.htm"
/>
<security:logout
logout-url="/zone4/secured/performLogout.htm"
logout-success-url="/zone4/simple/login.htm" />
<security:csrf disabled="true"/>
</security:http>
控制器:
/**
*
*/
package com.eej.ssba2.controller.test;
import java.io.IOException;
import java.util.Arrays;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.eej.ssba2.model.test.zone4.RegisterModel;
import com.eej.ssba2.model.test.zone4.RegisterModelValidator;
/**
*
*/
@Controller
@RequestMapping("/zone4")
public class Zone4TestController {
private Logger logger = Logger.getLogger(this.getClass());
@Resource(name="mainAuthenticationManager")
private AuthenticationManager authenticationManager;
@Resource(name="savedRequestSuccesHandler")
private SavedRequestAwareAuthenticationSuccessHandler successHandler;
@RequestMapping("/simple/unsecuredPage.htm")
public String unsecuredPage(){
return "simple/unsecuredPage";
}
@RequestMapping("/secured/securedPage.htm")
public String securedPage1(){
return "simple/secured/securedPage";
}
@RequestMapping("/secured/securedPage2.htm")
public String securedPage2(){
return "simple/secured/securedPage2";
}
@RequestMapping("/secured/securedPage3.htm")
public String securedPage3(){
return "simple/secured/securedPage3";
}
@RequestMapping("/simple/login.htm")
public String login(){
return "simple/login/login";
}
@RequestMapping(value="/simple/register.htm", method=RequestMethod.GET)
public String register(ModelMap model){
logger.debug("Entrada en register.htm");
if(!model.containsAttribute("registerModel")){
model.addAttribute("registerModel", new RegisterModel());
}
return "simple/login/register";
}
@RequestMapping(value="/simple/register.htm", method=RequestMethod.POST)
public String register(
HttpServletRequest request, HttpServletResponse response,
@Valid RegisterModel registerModel, ModelMap model, BindingResult bindingResult){
logger.info("entrada en register");
RegisterModelValidator userValidator = new RegisterModelValidator();
userValidator.validate(registerModel, bindingResult);
if(bindingResult.hasErrors()){
logger.info("BindingResult has errors: " + bindingResult.getAllErrors());
model.addAttribute("errors", bindingResult.getAllErrors());
model.addAttribute("registerModel", registerModel);
return "simple/login/register";
}
// Your user register business
Authentication authenticated = null;
/*
* If the user is created at this time due to your business logic, you could authenticate it directly
* through the manager
*
authenticated =
this.authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
registerModel.getMail1(),
registerModel.getPassword1()
)
);
*/
authenticated = new UsernamePasswordAuthenticationToken(
registerModel.getMail1(),
registerModel.getPassword1(),
Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"))
);
SecurityContextHolder.getContext().setAuthentication(authenticated);
try {
this.successHandler.onAuthenticationSuccess(request, response, authenticated);
} catch (ServletException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
注册模型bean:
package com.eej.ssba2.model.test.zone4;
import java.io.Serializable;
import javax.validation.Valid;
import javax.validation.constraints.Pattern;
import org.apache.log4j.Logger;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import com.eej.ssba2.ApplicationVersion;
/**
*
*
*/
public class RegisterModel implements Serializable{
private Logger logger = Logger.getLogger(this.getClass());
/**
*
*/
private static final long serialVersionUID = 1L;
@NotEmpty
@Pattern(regexp = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*" +
"@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$|")
public String mail1;
@NotEmpty
@Pattern(regexp = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*" +
"@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$|")
public String mail2;
@NotEmpty
public String password1;
@NotEmpty
public String password2;
// getters and setters
}
我用来验证模型中的字段的验证器实现:
package com.eej.ssba2.model.test.zone4;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
public class RegisterModelValidator implements Validator {
@Override
public boolean supports(Class<?> arg0) {
return RegisterModel.class.equals(arg0);
}
@Override
public void validate(Object target, Errors errors) {
RegisterModel user = (RegisterModel) target;
if(!user.getMail1().equals(user.getMail2())){
errors.rejectValue("mail1", "lbl_mail1_and_mail2_must_be_equal");
errors.rejectValue("mail2", "lbl_mail1_and_mail2_must_be_equal");
}
if(!user.getPassword1().equals(user.getPassword2())){
errors.rejectValue("password1", "lbl_pass1_and_pass2_must_be_equal");
errors.rejectValue("password2", "lbl_pass1_and_pass2_must_be_equal");
}
}
最后是注册jsp:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Login</title>
</head>
<body>
<form:form role="registerModel" commandName="registerModel" method="POST" action="${pageContext.request.contextPath}/zone4/simple/register.htm">
<form:errors path="*" cssClass="errorblock" element="div" />
<fieldset>
<div class="form-group">
<form:input path="mail1" id="mail1" name="mail1" placeHolder="email" />
<form:errors path="mail1" id="mail1" name="mail1" placeHolder="email" cssClass="error" />
</div>
<div class="form-group">
<form:input path="mail2" id="mail2" name="mail2" placeHolder="email" />
<form:errors path="mail2" id="mail2" name="mail2" placeHolder="email" cssClass="error" />
</div>
<div class="form-group">
<form:input path="password1" id="password1" name="password1" placeHolder="password" />
<form:errors path="password1" id="password1" name="password1" placeHolder="password" cssClass="error" />
</div>
<div class="form-group">
<form:input path="password2" id="password2" name="password2" placeHolder="password" />
<form:errors path="password2" id="password2" name="password2" placeHolder="password" cssClass="error" />
</div>
<div class="checkbox">
<label>
<input name="remember-me" id="remember-me" type="checkbox" value="Remember Me">Remember Me
</label>
</div>
<!-- Change this to a button or input when using this as a form -->
<button type="submit" class="btn btn-lg btn-success btn-block" name="submit"><spring:message code="lblRegistration"/></button>
</fieldset>
</form:form>
</body>
</html>