스프링 시큐리티 - Form Login 인증

SeungTaek·2022년 2월 11일
1
post-thumbnail

본 게시물은 스스로의 공부를 위한 글입니다.
잘못된 내용이 있으면 댓글로 알려주세요!

Form login이 무엇인지 알고 있다는 전제를 바탕으로 스프링 시큐리티 설정 부분을 설명한 게시물입니다.

먼저 설정 코드를 보자.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated();

        http.formLogin() // form 로그인 인증 기능이 작동함
                .loginPage("/loginPage") // 사용자 정의 로그인 페이지, default: /login
                .defaultSuccessUrl("/") // 로그인 성공 후 이동 페이지
                .failureUrl("/login") // 로그인 실패 후 이동 페이지
                .usernameParameter("userId") // 아이디 파라미터명 설정, default: username
                .passwordParameter("passwd") // 패스워드 파라미터명 설정, default: password
                .loginProcessingUrl("/login_proc") // 로그인 Form Action Url, default: /login
                .successHandler( ...생략... ) // 로그인 성공 후 핸들러
                .failureHandler( ...생략... ) // 로그인 실패 후 핸들러
                .permitAll(); // loginPage 접근은 인증 없이 접근 가능
    }
}
  1. .loginPage 로그인 페이지 주소를 설정할 수 있다. 사용자가 로그인 페이지를 직접 만들거나 로그인 주소를 변경할 때 사용된다. 기본 주소는 /login이다.
  2. .defaultSuccessUrl: 로그인 성공 후 자동으로 이동할 페이지이다.
    • 로그인 성공 후 redirect될 페이지를 정하는 것은 이 메소드 뿐이 아니다. .successHandler에서 send.redirect해줄 수도 있고, requestCache에서 직전에 접속하려 했던 url을 get해서 그 페이지로 이동하기도 한다. 그 중 .defaultSuccessUrl은 최후순위를 가지게 된다. 만약 이걸로 설정한 url로 무조건 리다이렉트가게 하고 싶다면 .defaultSuccessUrl("/home", true)같이 뒤에 인자로 true를 주면 된다.
  3. .failureUrl: 로그인 실패 후 자동으로 이동할 페이지이다.
  4. .usernameParameter: 아이디(username) 파라미터를 커스텀으로 정할 수 있다. 기본값은 username이다.
  5. .passwordParameter: 비밀번호 파라미터를 커스텀으로 정할 수 있다. 기본값은 password이다.
  6. .loginProcessingUrl: 로그인 Form Action Url을 지정할 수 있다. 기본값은 /login이다.
  7. .successHandler: 로그인 성공 이후 실행된다. 밑에서 자세히 알아보자.
  8. .failureHandler: 로그인 실패 이후 실행된다. 밑에서 자세히 알아보자.
  9. 로그인 페이지와 로그인 정보를 전달할 action url은 .permitAll된다. 즉, 인증이 없이 접근이 가능하다. 로그인을 하기 위한 로그인은 필요없다.

로그인 페이지 만들 때 주의할 점

사용자가 직접 로그인 페이지를 제작할 경우 주의할 점은 다음과 같다.

  • .usernameParameter( 아이디 name ) Id input의 name을 이 설정과 맞춰야 한다.
  • .passwordParameter( 비밀번호 name ) Password input의 name을 이 설정과 맞춰야 한다.
  • .loginProcessingUrl( Action Url ) 로그인의 Form Action Url과 맞춰야 한다.

위 3개는 html의 <form> , <Input>와 맞춰야 한다.


만약 기본 로그인 페이지를 사용하면서 다음과 같이 설정했다고 하자.

.usernameParameter("userId")
.passwordParameter("passwd")
.loginProcessingUrl("/login_proc")

그렇다면 로그인 페이지의 소스코드가 다음과 같이 바뀐것을 확인할 수 있다.


successHandler, failureHandler

파라미터로 각각 AuthenticationSuccessHandlerAuthenticationFailureHandler를 받게 된다.
오버라이드 메소드는 각각onAuthenticationSuccessAuthenticationFailureHandler이다. 이 메소드의 파라미터를 보면 알겠지만 request와 Authentication를 받을 수 있다. 또한 response도 파라미터로 받으면서 헤더에 값을 넣는 등의 행위를 할 수 있다.
익명 객체를 사용한 예시는 다음과 같다.

.successHandler( // 로그인 성공 후 핸들러
  new AuthenticationSuccessHandler() { // 익명 객체 사용
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
      System.out.println("authentication: " + authentication.getName());
      response.sendRedirect("/");
    }
  })
.failureHandler( // 로그인 실패 후 핸들러
  new AuthenticationFailureHandler() { // 익명 객체 사용
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
      System.out.println("exception: " + exception.getMessage());
      response.sendRedirect("/login");
    }
  })

form 인증 과정

로그인 인증은 UsernamePasswordAuthenticationFilter에 의해 진행된다.

  1. AntPathRequestMatcher(/login) : 로그인 요청이 올바른 url로 들어왔는지 확인(.loginProcessingUrl()로 커스텀 가능)
  2. 인증객체(Authentication) 객체 생성(Username과 password를 담음)
  3. 위에서 만든 객체를 이용해 AuthenticationManager에서 인증처리 (내부적으로 AuthenticationProvider에게 인증 위임)
    • 인증 실패시 AuthenticationExcepion
    • 인증 성공시 Authentication객체를 만들어서 리턴(User 정보와 권한 정보 등을 담음)
  4. Authentication객체를 SecurityContext에 저장 -> Session에 저장(전역으로 사용 가능하게 함)
  5. SuccessHandler 실행


위 이미지는 스프링 시큐리티를 공부해봤다면 한번쯤은 봤을 유명한 이미지이다.
여기서 UsernamePasswordAuthenticationToken의 부모가 Authentication이다.


인증 객체와 Security Context

여기서 중요한게 인증 객체(Authentication)와 SecurityContext이다. 스프링 시큐리티를 공부하면 정말 많이 마주치게 되는 단어이다.

먼저 인증 객체(Authentication)는 스프링 시큐리티가 내부적으로 사용하는 객체이다. 아이디, 비밀번호, 회원 정보나 권한 등을 담을 수 있는 객체이며, 사용자가 객체에 담을 정보를 커스텀 할 수도 있다.

SecurityContext는 결국 서버의 세션이다. 세션 중에서 스프링 시큐리티가 사용하는 특별한 공간이기도 하다. 인증객체(SecurityContext)를 이 세션 공간에 저장하게 된다. 이 세션은 전역적으로 꺼내 사용할 수 있는 공간이다.

여기에서 더 자세하게 알아볼 수 있다.



Reference

인프런 '스프링 시큐리티 - Spring Boot 기반으로 개발하는 Spring Security' (정수원)

profile
I Think So!

0개의 댓글