代码之家  ›  专栏  ›  技术社区  ›  Mahmoud Saleh

注册成功后自动登录

  •  29
  • Mahmoud Saleh  · 技术社区  · 15 年前

    大家好 我想在春季注册成功后自动登录 含义: 我想在注册后跳过登录页面,自动登录,这样用户就可以看到受保护的页面,明白吗? 怎么做?

    10 回复  |  直到 9 年前
        1
  •  43
  •   nyxz    11 年前

    这可以通过以下方式使用spring security完成(半伪代码):

    import org.springframework.security.web.savedrequest.RequestCache;
    import org.springframework.security.web.savedrequest.SavedRequest;
    
    @Controller
    public class SignupController
    {
    
        @Autowired
        RequestCache requestCache;
    
        @Autowired
        protected AuthenticationManager authenticationManager;
    
        @RequestMapping(value = "/account/signup/", method = RequestMethod.POST)
        public String createNewUser(@ModelAttribute("user") User user, BindingResult result,  HttpServletRequest request, HttpServletResponse response) {
            //After successfully Creating user
            authenticateUserAndSetSession(user, request);
    
            return "redirect:/home/";
        }
    
        private void authenticateUserAndSetSession(User user, HttpServletRequest request) {
            String username = user.getUsername();
            String password = user.getPassword();
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
    
            // generate session if one doesn't exist
            request.getSession();
    
            token.setDetails(new WebAuthenticationDetails(request));
            Authentication authenticatedUser = authenticationManager.authenticate(token);
    
            SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
        }
    }
    

    更新:仅包含注册后如何创建会话

        2
  •  13
  •   Henok T    10 年前

    在Servlet3+中,您只需 request.login("username","password") 如果成功,重定向到你想要的任何页面。您可以对自动注销执行相同的操作。

    以下是文档中讨论此问题的部分的链接: http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#servletapi-3

        3
  •  8
  •   takrl cck    14 年前

    在应用程序中声明身份验证管理器时,需要设置别名-servlet.xml或应用程序上下文-安全.xml文件:

    <authentication-manager alias="authenticationManager>
        <authentication-provider>
            <user-service>
                <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
                <user name="bob" password="bobspassword" authorities="ROLE_USER" />
            </user-service>
        </authentication-provider>
    </authentication-manager>
    

    UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword());
    request.getSession();
    
    token.setDetails(new WebAuthenticationDetails(request));
    
    try{
        Authentication auth = authenticationManager.authenticate(token);
    
        SecurityContextHolder.getContext().setAuthentication(auth);
    } catch(Exception e){
            e.printStackTrace();
    }
    
    return "redirect:xxxx.htm";
    
        4
  •  2
  •   andy    11 年前
    1. 配置网站.xml允许Spring安全性处理登录处理url的转发。
    2. 处理注册请求,例如创建用户、更新ACL等。
    3. 获得整个弹簧安全过滤器链的好处,例如会话固定保护。

    因为转发是内部的,所以在用户看来就好像它们是在同一请求期间注册和登录的一样。

    如果您的注册表不包含正确的用户名和密码参数名称,请转发请求的修改版本(使用 HttpServletRequestWrapper

    为了让它工作,你必须修改你的网站.xml使弹簧安全过滤器链把手向前移动 login-processing-url . 例如:

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    
    <!-- Handle authentication for normal requests. -->
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <!-- Handle authentication via forwarding for internal/automatic authentication. -->
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/login/auth</url-pattern>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>
    

    Source: mohchi blog

        5
  •  2
  •   Rahul Gupta    7 年前

    我合并了相同的场景,下面是代码片段。要获取AuthenticationManager的实例,需要重写WebSecurityConfigureAdapter类的authenticationManagerBean()方法

    (扩展Web安全配置适配器)

    @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    

    控制器

        @Autowired
        protected AuthenticationManager authenticationManager;
    
        @PostMapping("/register")
        public ModelAndView registerNewUser(@Valid User user,BindingResult bindingResult,HttpServletRequest request,HttpServletResponse response) {
            ModelAndView modelAndView = new ModelAndView();
            User userObj = userService.findUserByEmail(user.getEmail());
            if(userObj != null){
                bindingResult.rejectValue("email", "error.user", "This email id is already registered.");
            }
            if(bindingResult.hasErrors()){
                modelAndView.setViewName("register");
                return modelAndView;
            }else{
                String unEncodedPwd = user.getPassword();
                userService.saveUser(user);
                modelAndView.setViewName("view_name");
                authWithAuthManager(request,user.getEmail(),unEncodedPwd);
            }   
            return modelAndView;
        }
    
    
        public void authWithAuthManager(HttpServletRequest request, String email, String password) {
            UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(email, password);
            authToken.setDetails(new WebAuthenticationDetails(request));
            Authentication authentication = authenticationManager.authenticate(authToken);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
    
        6
  •  1
  •   Ankit Pandoh    8 年前

    例如,假设在我的例子中,当用户重置密码时,我希望他在不再次登录的情况下进入仪表板。当我使用上述方法时,它将我带到仪表板,但它绕过了我应用的并发过滤器,以避免并发登录。下面是一段代码:

    UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(empId, password);
    Authentication auth = authenticationManager.authenticate(authToken);
    SecurityContextHolder.getContext().setAuthentication(auth);
    

    <form-login login-page="/login" 
                always-use-default-target="false" 
                default-target-url="/target-url" 
                authentication-failure-url="/login?error"
                login-processing-url="/submitLogin"/>
    

    网站.xml

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/submitLogin</url-pattern>
        <dispatcher>FORWARD</dispatcher>
     </filter-mapping>
    

    通过在网站.xml实际上,它负责转发您在自动登录期间发出的显式转发请求,并将其传递给spring安全过滤器链。

    希望有帮助

        7
  •  0
  •   Community Mohan Dere    9 年前

    Spring Monkey's answer works great

    <http pattern="/register/**" security="none"/>
    

    我不得不将注册页旁路设置为IS\u AUTHENTICATED\u匿名

    <http authentication-manager-ref="authMgr">
      <intercept-url pattern="/register/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
      ...
    </http>
    
        8
  •  0
  •   Yogesh Devgun    9 年前

    这是对上述问题的回答

    @RequestMapping(value = "/registerHere", method = RequestMethod.POST)
        public ModelAndView registerUser(@ModelAttribute("user") Users user, BindingResult result,
                HttpServletRequest request, HttpServletResponse response) {
            System.out.println("register 3");
    
            ModelAndView mv = new ModelAndView("/home");
            mv.addObject("homePagee", "true");
    
            String uname = user.getUsername();
    
            if (userDAO.getUserByName(uname) == null) {
    
                String passwordFromForm = user.getPassword();
                userDAO.saveOrUpdate(user);
    
                try {
                    authenticateUserAndSetSession(user, passwordFromForm, request);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
    
    
            }
    
            System.out.println("register 4");
    
            log.debug("Ending of the method registerUser");
            return mv;
        }
    

    控制器中的上述方法定义如下:

    `private void authenticateUserAndSetSession(Users user, String passwor`dFromForm, HttpServletRequest request){
    
            String username = user.getUsername();
            System.out.println("username:  " + username + " password: " + passwordFromForm);                        
    
            UserDetails userDetails = userDetailsService.loadUserByUsername(user.getUsername());
    
            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(username, passwordFromForm, userDetails.getAuthorities());
            request.getSession();
    
            System.out.println("Line Authentication 1");
    
            usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetails(request));
    
            System.out.println("Line Authentication 2");
    
            Authentication authenticatedUser = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
    
            System.out.println("Line Authentication 3");
    
    
            if (usernamePasswordAuthenticationToken.isAuthenticated()) {
                SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
                System.out.println("Line Authentication 4");
    
            }
    
         request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());// creates context for that session.
    
            System.out.println("Line Authentication 5");
    
            session.setAttribute("username", user.getUsername());
    
            System.out.println("Line Authentication 6");
    
            session.setAttribute("authorities", usernamePasswordAuthenticationToken.getAuthorities());
    
            System.out.println("username:  " + user.getUsername() + "password: " + user.getPassword()+"authorities: "+ usernamePasswordAuthenticationToken.getAuthorities());
    
            user = userDAO.validate(user.getUsername(), user.getPassword());
            log.debug("You are successfully register");
    
        }
    

    其他答案并没有建议把它放在try/catch中,所以人们不知道为什么逻辑不能在代码运行时工作……控制台上也没有任何错误或异常。所以,如果你不把它放在try-catch中,你就不会得到坏凭证的例外。

        9
  •  0
  •   Dillon Ryan Redding Gandalf    8 年前

    @PostMapping("/signup")
    public String signUp(User user) {
        // encode the password and save the user
        return "forward:/login";
    }
    

    假设你有 username password 字段,然后“forward”将发送这些参数,Spring Security将使用这些参数进行身份验证。

    我发现这种方法的好处是你不会重复你的想法 formLogin defaultSuccessUrl (下面是安全设置示例)。它还通过不需要 HttpServletRequest 参数。

    @Override
    public void configure(HttpSecurity http) {
        http.authorizeRequests()
                .antMatchers("/", "/signup").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/home", true)
                .permitAll();
    }
    
        10
  •  -1
  •   sinuhepop    15 年前

    我不确定您是否要求这样做,但是在您的Spring安全配置中,您可以添加一个“rememberme”标记。这将管理您的客户端中的cookie,因此下次(如果cookie尚未过期)您将自动登录。

    <http>
        ...
        <remember-me />
    </http>