Spring安全性:新用户工作流程

时间:2016-09-12 05:21:49

标签: spring spring-mvc spring-security

我是Spring安全新手。

我创建了一个自定义表单,用于登录用户,然后在成功登录后,用户继续访问他/她的预期网页。我的实现是标准的,它可以工作。

这是我的问题。

  • 用户想要转到 mywebpage.html 页面。
  • 用户未登录 用户被(由Spring Security重定向)到登录页面。
  • 用户 没有帐户。
  • 用户点击createAccount链接 并通过标准的MVC协议进入注册页面。

我现在如何从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;
}

1 个答案:

答案 0 :(得分:1)

您可以使用SavedRequestAwareAuthenticationSuccessHandler

当未经授权的请求到达ExceptionTranslationFilter时,会创建RequestCacheHttpSessionRequestCache,并在其上保存原始请求。

这样,如果您未将>>> 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");
            }
        }