我是Spring安全新手。
我创建了一个自定义表单,用于登录用户,然后在成功登录后,用户继续访问他/她的预期网页。我的实现是标准的,它可以工作。
这是我的问题。
我现在如何从Spring Security获取用户最初预期的目的地(mywebpage.html),以便我可以在用户创建帐户后将用户重定向到该页面?
记录,security.xml
<http auto-config="true">
<intercept-url pattern="/login" access="permitAll()" />
<intercept-url pattern="/flow-entry.html" access="hasRole('ROLE_USER')"/>
<form-login
login-page="/login"
authentication-failure-url="/login?error=true" />
<logout logout-success-url="/login" />
</http>
登录表单
<form name='f' action="login" method='POST'>
<table style="text-align:left" class="w3-table" >
<tr style="text-align:center;color:red" th:if="${loginresponse}">
<td colspan="2" style="text-align:center" th:text="#{${loginresponse}}"> </td>
</tr>
<tr>
<td th:text="#{label.emaillogin}"></td>
<td><input type="text" name="username" value=''/></td>
</tr>
<tr>
<td th:text="#{label.password}">Password:</td>
<td><input type="password" name="password" /></td>
</tr>
<tr>
<td colspan="2" style="text-align:center"><input name="submit" type="submit" class="w3-btn w3-blue w3-hover-aqua w3-round-large" th:value="#{label.ok}" /></td>
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
</tr>
<tr style="text-align:center">
<td colspan="2" style="text-align:center"> <a href="./register"><span th:text="#{label.register}"></span></a> </td>
</tr>
</table>
</form>
控制器方法。我在此方法中需要最初预期的网页
@RequestMapping(value = "/doRegistration", method=RequestMethod.POST)
public ModelAndView doRegistration(ModelAndView mv, HttpServletRequest request)
{
mv.setViewName("register");
SSm.getLogger().debug("registering new user");
String email = request.getParameter("username");
String email1 = request.getParameter("username1");
if(email.equals(email1))
{
if(email.contains("@")&&email.contains("."))
{
SSm.getLogger().debug("got legit email");
String password = request.getParameter("password");
String password1 = request.getParameter("password1");
if(password.equals(password1))
{
SSm.getLogger().debug("ready to login");
I NEED USERS ORIGINALLY INTENDED DESTINATION RIGHT HERE SO I CAN SET THE VIEW
}
else
{
mv.setViewName("register");
mv.addObject("loginresponse", "message.passwordmismatch");
}
}
else
{
mv.setViewName("register");
mv.addObject("loginresponse", "message.invalidemail");
}
}
else
{
mv.setViewName("register");
mv.addObject("loginresponse", "message.emailmismatch");
}
return mv;
}
答案 0 :(得分:1)
您可以使用SavedRequestAwareAuthenticationSuccessHandler。
当未经授权的请求到达ExceptionTranslationFilter时,会创建RequestCache类HttpSessionRequestCache,并在其上保存原始请求。
这样,如果您未将>>> divmod(1664, 100)
(16, 64)
设置为true,则会重建httpRequest并将其用作目标URL,同时执行正确的登录。
因此,尝试使用@Autowire(我使用@Resource,因为我的安全配置中有多个AuthenticationManager和AuthenticationSuccessHandler),控制器中的AuthenticationSuccessHandler并调用alwaysUseDefaultTargetUrl
,如下所示:
我做了一些修改,例如使用determineTargetUrl()
注释并实施@Valid
来验证注册表单
的security.xml
Validator
控制器:
<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>
注册模型bean:
/**
*
*/
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;
}
}
我用来验证模型中字段的Validator imiplementation:
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
}
最后,注册jsp:
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");
}
}