복붙노트

[SPRING] 성공적인 등록 후 자동 로그인

SPRING

성공적인 등록 후 자동 로그인

모두 안녕 스프링 등록 성공 후 자동 로그인을하고 싶습니다. 의미: 나는 그들을 액세스하기 위해 로그인해야하는 보호 된 페이지가 있습니다. 그리고 나는 로그인 페이지를 건너 뛰고 자동 로그인을하여 사용자가 보호 된 페이지를 볼 수있게하고 싶습니다. 나는 봄 3.0, 봄 보안 3.0.2를 사용하고있다. 그렇게하는 방법?

해결법

  1. ==============================

    1.이것은 다음과 같은 방식으로 봄 보안을 사용하여 수행 할 수 있습니다 (준 의사 코드).

    이것은 다음과 같은 방식으로 봄 보안을 사용하여 수행 할 수 있습니다 (준 의사 코드).

    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. ==============================

    2.Servlet 3+에서는 단순히 request.login ( "username", "password")을 수행하고 성공할 경우 원하는 페이지로 리디렉션 할 수 있습니다. 자동 로그 아웃에 대해서도 동일한 작업을 수행 할 수 있습니다.

    Servlet 3+에서는 단순히 request.login ( "username", "password")을 수행하고 성공할 경우 원하는 페이지로 리디렉션 할 수 있습니다. 자동 로그 아웃에 대해서도 동일한 작업을 수행 할 수 있습니다.

    다음은이 설명서에 대한 링크입니다. http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#servletapi-3

  3. ==============================

    3.authenticationManager를 autowire하는 방법에 대한 첫 번째 회신에 대한 의견.

    authenticationManager를 autowire하는 방법에 대한 첫 번째 회신에 대한 의견.

    application-servlet.xml 또는 applicationContext-security.xml 파일에서 authentication-manager를 선언 할 때 별칭을 설정해야합니다.

    <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>
    

    또한 인증 할 때 AuthenticationException을 throw 할 수 있으므로 catch해야합니다.

    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. ==============================

    4.전달은 내부이므로 사용자가 동일한 요청 중에 등록되고 로그인 된 것처럼 보입니다.

    전달은 내부이므로 사용자가 동일한 요청 중에 등록되고 로그인 된 것처럼 보입니다.

    등록 양식에 올바른 사용자 이름과 암호 매개 변수 이름이 없으면 HttpServletRequestWrapper를 사용하여 수정 된 버전의 요청을 Spring Security 로그인 끝점으로 전달하십시오.

    이 작업을 수행하려면 web.xml을 수정하여 Spring Security 필터 체인이 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>
    

    출처 : mohchi blog

  5. ==============================

    5.SecurityContextHolder.getContext () 사용 setAuthentication (인증)은 작업을 완료하지만 보안 위험을 초래할 스프링 보안 필터 체인을 우회합니다.

    SecurityContextHolder.getContext () 사용 setAuthentication (인증)은 작업을 완료하지만 보안 위험을 초래할 스프링 보안 필터 체인을 우회합니다.

    예 : 필자의 경우 사용자가 암호를 재설정 할 때 다시 로그인하지 않고 대시 보드로 가져 오라고 말했습니다. 위의 방법을 사용하면 대시 보드로 이동하지만 동시 로그인을 피하기 위해 필자가 적용한 동시성 필터를 건너 뜁니다. 다음은 작업을 수행하는 코드 조각입니다.

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

    web.xml의 간단한 변경과 함께 login-processing-url 속성을 사용하십시오.

    보안 xml

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

    을 포함한다.

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

    web.xml에이 코드를 추가하면 실제로 자동 로긴 중에 명시된 순방향 요청을 포워딩하여 스프링 보안 필터 체인에 전달합니다.

    희망이 도움이된다.

  6. ==============================

    6.나는 동일한 시나리오를 통합했다. 아래는 코드 스 니펫이다. AuthenticationManager의 인스턴스를 가져 오려면 WebSecurityConfigurerAdapter 클래스의 authenticationManagerBean () 메서드를 재정의해야합니다.

    나는 동일한 시나리오를 통합했다. 아래는 코드 스 니펫이다. AuthenticationManager의 인스턴스를 가져 오려면 WebSecurityConfigurerAdapter 클래스의 authenticationManagerBean () 메서드를 재정의해야합니다.

    SecurityConfiguration (WebSecurityConfigurerAdapter 확장)

    @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);
        }
    
  7. ==============================

    7.봄 원숭이의 대답은 훌륭하게 작동하지만, 구현할 때 까다로운 문제가 발생했습니다.

    봄 원숭이의 대답은 훌륭하게 작동하지만, 구현할 때 까다로운 문제가 발생했습니다.

    내 문제는 등록 페이지가 "보안이 없음"으로 설정 되었기 때문입니다. 예 :

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

    나는 이것이 어떤 SecurityContext도 초기화되지 않았으며, 따라서 사용자 등록 후에는 서버 내 인증을 저장할 수 없다고 생각한다.

    나는 그것을 IS_AUTHENTICATED_ANONYMOUSLY로 설정함으로써 레지스터 페이지 바이 ​​패스를 변경해야했다.

    <http authentication-manager-ref="authMgr">
      <intercept-url pattern="/register/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
      ...
    </http>
    
  8. ==============================

    8.위 질문에 대한 답변입니다. 컨트롤러에서 :

    위 질문에 대한 답변입니다. 컨트롤러에서 :

    @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에 넣으려고하지 않았으므로 코드가 실행될 때 논리가 작동하지 않는 이유를 알지 못합니다. 콘솔에 오류나 예외도 없습니다. 그래서 만약 당신이 그것을 잡으려고 시도 못해 나쁜 자격 증명의 예외를 얻을.

  9. ==============================

    9.이것은 Servlet 3 + 통합에 대한 대안입니다. 스프링 시큐리티의 폼 로그인을 사용하고 있다면 로그인 페이지에 위임 할 수 있습니다. 예 :

    이것은 Servlet 3 + 통합에 대한 대안입니다. 스프링 시큐리티의 폼 로그인을 사용하고 있다면 로그인 페이지에 위임 할 수 있습니다. 예 :

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

    폼에 사용자 이름과 패스워드 필드가 있다고 가정하면 '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. ==============================

    10.당신이 이것을 요구하고 있는지 확신 할 수 없지만 Spring Security 구성에서 "remember-me"태그를 추가 할 수 있습니다. 이렇게하면 클라이언트의 쿠키가 관리되므로 다음에 쿠키가 만료되지 않은 경우 자동으로 로그인됩니다.

    당신이 이것을 요구하고 있는지 확신 할 수 없지만 Spring Security 구성에서 "remember-me"태그를 추가 할 수 있습니다. 이렇게하면 클라이언트의 쿠키가 관리되므로 다음에 쿠키가 만료되지 않은 경우 자동으로 로그인됩니다.

    <http>
        ...
        <remember-me />
    </http>
    
  11. from https://stackoverflow.com/questions/3813028/auto-login-after-successful-registration by cc-by-sa and MIT license