SpringSecurity(2-1. 로그인)

Walker·2021년 7월 4일
0

SpringSecurity

목록 보기
2/4
post-thumbnail

지난 글에서 스프링 시큐리티의 전체적인 그림을 보았다.
이제는 실제로 로그인을 구현하며 각 필터나 기능이 어떻게 쓰이는지 알아보자!

스프링 시큐리티에서 로그인 상태의 의미는 인증 정보가 true인 Authentication 객체
SecurityContext에 담겨져 있는 상태를 의미한다.

위의 그림을 통해 보자면 Authentication 객체가 SecurityContext에 담겨 있고
담기기 전에 AuthenticationManager가 Authentication 객체를 인증한다.

이렇게 보면 Session이랑 SecurityContenxt
결국 사용자 정보를 담고 있다는 점에서 크게 다르지않은 것 같은데
왜 스프링 시큐리티에서는 굳이 분리하여 사용하는가에 대한 의문이 생겼다.

출처: https://brunch.co.kr/@sbcoba/11

이중 내 수준에서 이해할 수 있는 이유는 첫번째의 서블릿 의존성 때문이었다.
Session(HttpSession)의 경우 기본적으로 서블릿의 인터페이스이다.(javax.servlet.http.HttpSession)
https://lindarex.github.io/concepts/java-httpsession-introduction
따라서 위의 설명처럼 서블릿이 아닌 일반 APP에서는 Session 사용이 어렵다.

Authentication 객체에는 위와 같은 정보들이 들어있는데
실제 사용 할 때는 principal안에 있는 User 정보를 많이 활용하는 듯 하다.

실제 로그인을 구현할 때 가장 많이 쓰이는 필터는
UsernamePasswordAuthenticationFilter이다.(이름 너무 길다...)

UsernamePasswordAuthenticationFilter의 주요 설정은 위와 같다.

  1. 어떤 url로 POST 요청을 보낼지(form의 action = url과 유사)
  2. ID/PW 인자를 넘겨줄 때 파라미터로 받는 이름 지정
  3. 로그인 성공/실패 시 처리할 방법

이를 실제 코드로 작성하면 위와 같고
이 중 defaultSuccessUrl()의 경우 alwaysUse : false 값을 주는 이유는
로그인 시 무조건 설정한 defaultSuccessUrl("/main")으로 가는 것을 막기 위해서이다.
(쇼핑몰에서 상품을 보다 로그인을 하면, 보던 상품 페이지가 아니라 main으로 가는 것을 방지)

attemptAuthentication은 UsernamePasswordAuthenticationFilter의
주요 메소드로 필요에 따라 수정 할 수 있다.
위의 authRequest의 Token은 아직 true가 아닌 상태
AuthenticationManager에게 보내면 인증하여 true 상태로 변경해준다.

로그인에 대한 이해는 여기까지 하고 실제 구현과정은 다음과 같다.

기획은 위와 같이 useradmin이 각각 로그인을 할 수 있도록 하고
권한에 따라 접근할 수 있는 페이지가 다르며
권한이 없을 경우 access-denided 페이지로 가게된다.

먼저 메인 페이지("/")는 모든 요청을 허가하고(permitAll())
이외의 다른 요청에는 모두 인증을 요구(authenticated())하는 설정이다.
(메인 페이지 외에는 로그인이 되어야 접근이 가능한 상태가 된다.)

이렇게만 설정을 하면 생기는 문제는 css 파일과 같은 자원의 경로도
인증을 요구하는 상태가 되어 디자인이 적용되지 않는 것이다.

이를 해결하기 위해서는 web의 리소스에 대한 인증 요구를 무시하는 설정을 해줘야 하며
PathReques.toStaticResources().atCommonLocations()에 해당하는 경로는 아래와 같다.
(아래와 같은 경로에 있는 파일들은 인증 요구를 무시 할 수 있게 된다.)
(resources/static/css||js||images||webjars||favicon||...)

이를 통해 css가 적용된 메인페이지는 위와 같다.

이제 로그인을 통해 인증을 받으려면 UsernamePasswordAuthenticationFilter를 통해야하고
이를 위해서는 formLogin()을 사용하면 된다.
(만약 formLogin()을 사용하지 않고 바로 UserPage등으로 접근하면 403 에러가 발생한다.)

formLogin()을 사용후 로그인이 되지 않은 상태로 Page에 접근하면
위와 같이 기본 로그인 창이 나오게되며 이를 통한 인증을 요구한다.

기본 로그인 창이 아닌 구현한 로그인 페이지를 만들었다면
그 접근 url("/login")을 지정하고 permitAll()을 꼭 해줘야 한다.
왜냐하면 "/login" 페이지 자체도 authenticated()를 받아야 하는 페이지이기 때문에
"/login" > 인증 요구 > "/login" > 인증 요구... 이런 식으로 무한 루프가 되어버린다.

여기까지 하게되면 비로소 구현한 로그인 페이지에 접근 할 수 있게되고
이후 로그인을 진행 할 수 있다.
다음 글에서는 로그인 과정권한 처리등을 살펴보자~!

profile
I walk slowly, but I never walk backward. -Abraham Lincoln-

0개의 댓글