인증 프로세스

황상익·2024년 9월 3일

security

목록 보기
2/16

폼 인증

HTTP 기반 폼 로그인 인증 메커니즘을 활성화 API, 사용자 인증을 위한 사용장의 정의 로그인 페이지를 쉽게 구현
기본 로그인 페이지를 사용, 사용자 이름과 비밀번호 필드가 포함된 로그인 양식을 제공
사용자는 웹 폼을 통해 자격 증명 제공, SpringSecurity는 HttpServletRequest에서 값이 나온다.

client → AuthorizationFilter (사용자 접근 가능 한지 유무 판단) → AccessDeniedException (인증 받지 못한 사용자면 예외) → Exception transactionFilter(인증을 받지 못한 사용자 예외 발생) → AuthenticationEntityPoint (다시 인증 받도록 하는 일) → 로그인 페이지 → form → 인증 시도 → server

formLoginAPI

formLoginConfigurer 설정 클래스를 통해 여러 API를 설정 가능
내부적으로 UsernamePasswordAuthenticationFilter가 들어있다.

인증 설정 API
loginPage - 사용자 정의 로그인 페이지로 전환, 기본 로그인 페이지 무시
loginProcessingUrl - 사용자 이름과 비밀번호 검증할 URL 정의 (form action)
defaultSuccessUrl - 로그인 성공 이후 이동 페이지. alwaysUse가 true이면 무조건 저장 위치로, 인증 전에 보안이 필요한 페이지를 방문하다가 인증에 성공한 경우 → redirect

failureUrl - 인증에 실패했을때 이동할 페이지 → 기본값은 로그인 페이지로 이동
usernameParameter - 인증을 수행할때 사용자 이름을 찾기 위해 확인하는 HTTP 매개변수 설정. 기본값은 username
passwordParameter - 인증을 수행할때 비밀번호를 찾기위해 확인하는 HTTP 매개변수 설정, 기본값은 password

failureHandler(AuthenticationFailureHandler) - 인증 실패 → AuthenticationFailureHandler를 지정
기본값은 SimpleUrlAuthenticationHandler를 사용하여 /login?error로 리다이렉트,
successHandler(AuthenticationFailureHandler) - 인증에 성공할 경우 AuthenticationSuccessHandler 기본값은 SavedRequestAwareAuthenticat ionSuccessHandler

permitAll() - failureUrl, loginProcessingUrl, loginPage에 대한 URL 모든 사용자 접근 허용

+)failureHandler →

init - 기본적 setting
configure - 여러가지 인증, 핵심적 기능 담당

UsernamePasswordAuthenticationFilter (인증 필터)

스프링 시큐리티는 AbstarctAuthenticationProcessingFilter 클래스를 사용자의 자격증명 인증하는 기본 필터

UsernamePasswordAuthenticationFilter는 AbstarctAuthenticationProcessingFilter를 확장한 클래스 , HttpServletRequest에서 제출된 사용자의 이름, 비밀번호로 부터, 인증을 수행

인증 프로세스가 초기화 → 로그인 페이지와 로그아웃 페이지 생성을 위한 DefaultLoginPageGeneratingFilter 및 DefaultLogoutPageGeneratingFilter 초기화

인증을 받기 위해 로그인 페이지 로그아웃 생성 → filter가 작업 한다.

yes case

UsernamePasswordAuthenticationFilter → requestMatcher (login 정보 o) → UsernamePasswordAuthenticationToken → AuthenticationManager → UsernamePasswordAuthenticationToken (username + password) → UsernamePasswordAuthenticationToken (UserDetails + Authorities)→ SessionAuthenticationStartegy (새로운 로그인 알리고, 세션 관련 작업 수행)→ SecurityContextHolder (Authentication을 SecurityContext에 설정 & 세션에 SecurityContext 저장) //사용자 인증상태 유지→ RememberMeServices(RememberMeServices.loginSuccess 호출 / 자동로그인) → ApplicationEventPublisher → AutheticationSuccessHandler

No case

UsernamePasswordAuthenticationFilter → requestMatcher (login 정보 o) → chain.doFilter

UsernamePasswordAuthenticationFilter → requestMatcher (login 정보 o) → UsernamePasswordAuthenticationToken → AuthenticationManager → SecurityContextHolder (SecurityContextHolder가 삭제 → 인증에 실패 했기 때문)→ RememberMeServices (RememberMeServices.loginSuccess 호출)→ AuthenticationFailureHandler
인증에 실패하게 되면 예외 처리 → 인증에 처리 하는 도중, Handler에서 보통 이 작업을 한다. / 인증 필터에서 처리

HttpBasic 인증

HTTP 엑세스 제어와 인증을 위한 프레임워크를 제공, 가장 일반적 인증방식은 “basic” 인증 방식

RFC 7235 표준이며, 프로토콜은 Http인증 헤더에 기술
1. 클라이언트는 인증정보 없이 서버로 접속 시도
2. 서버가 클라이언트에게 인증 요구를 보낼때 401 응답과, WWW-Authentication 헤더를 기술해서 realm 보장영역, basic 인증방법을 보냄
3. 클라이언트가 서버로 접속, Base64로 username, password를 인코딩, Authentication 헤더에 담아서 요청
4. 성공적 요청시, 상태코드 반환

+) base64 인코딩 된 값은 디코딩이 가능, 인증정보 노출
HTTP basic 인증은 Https와 같이 TLS 기술과 함께 사용

httpBasic() API

httpBasicConfigurer 설정 클래스를 통해 API 설정
내부적으로 BasicAuthenticationFilter가 생성되어 기본 인증 방식의 인증 처리를 담당

HttpSecurity.httpBasic(httpSecurityHttpBasicConfigurer -> httpSecurityHttpBasicConfigurer
.realmName(“security") //HTTP기본영역을설정한다
. authenticationEntryPoint( //커스텀하게 설정 가능

request, response, authException); //단순하게 로그인 페이지 이동 목적이라면, 기본 기능만 사용해도 됨

authenticationEntryPoint → 인증에 실패시 호출, 기본값은 realm 영역으로 BasicAuthenticationFilter

BasicAuthenticationFilter

기본 인증 서비스 제공
BasicAuthenticationConverter를 사용해서 헤더에 기술된 인증정보의 유효성 체크, Base64 인코딩된 username, passwrod 추출
인증 이후 세션을 사용하는 경우와 사용하지 않는 경우에 따라 처리되는 흐름 차이 있음

세션을 사용하는 경우 매 요청마다 인증과정을 거치지 않으며, 세션을 사용하지 않는 경우 매 요청마다 인증과정 거쳐야 함

BasicAuthenticationFilter → UsernamePasswordAuthenticationToken → AuthenticationManager → N → SecurityContextHolder (Security Context 삭제) → RememberMeService (RememberMeService.loginFail 호출) → AuthenticationEntryPoint 호출

BasicAuthenticationFilter → UsernamePasswordAuthenticationToken → AuthenticationManager (인증처리) → Y → UsernamePasswordAuthenticationToken → SecurityContextHolder(Authentication을 SecurityContext에 설정 → 저장 / 요청범위 내에서) → RememberMeService (RememberMeService.loginSuccess 호출) → chain.doFilter

formLogin → session에 값을 저장

SecurityRepository → session X (requestAttributeSecurityContextRepo) 값을 저장

RememberMe

사용자가 웹사이트나 애플리케이션에 로그인시 자동으로 인증정보를 기억하는 기능
UsernamepasswordAuthenticationFilter와 함께 사용, AbstractAuthentictaionProcessingFilter 슈퍼클래스에서 훅을 통해 구현

  • 인증 성공시 RememberMeService.loginFail 호출 → 토큰을 생성하고 쿠키로 전달
  • 실패시 RememberMeService.loginFail 호출 → 쿠키를 지움
  • LogoutFilter와 연계해서 로그아웃 시 쿠키를 지움

토큰 생성

기본적으로 암호화된 토큰으로 생성, 브라우저에 쿠키를 보내고 향후 세션에서 쿠키를 감지하여 자동로그인 (단방향이기 때문에 값을 해석할 수 없음) → 암호화

base64(username + ":" + expirationTime + ":" + algorithmName + ":" algorithmHex(username + ":" + expirationTime + ":" password + ":" + key)) → 16 진수로 된 hash 값

  • username : UserDetailsService로 식별 가능한 사용자 이름
  • password : 검색된 UserDetails에 일치하는 비밀번호
  • expirationTime : remember-me 토큰 만료 시간 날짜 밀리초
  • key : remember-me 토큰의 수정을 방지
  • algorithmName : remember-me 토큰을 서명을 생성, 검증하는데 사용

RememberMeServices 구현체

TokenBasedRemeberMeServices - 쿠키 기반 토큰의 보안을 위해 해싱을 사용 (메모리 방식) → 주로 사용
PersistentTokenBasedRemeberMeServices - 생성된 토큰을 저장하기 위해 DB나 다른 영구 저장매체를 사용

두 구현다 → UserDetailsServices 필요

RememberMeAPI

→ RememberMeConfigurer 설정클래스를 통해 여러API들을 설정 할 수 있다
내부적으로 RememberMeAuthenticationFilter가 생성되어 자동인증처리를 담당

- http.rememberMe(httpSecurityRememberMeConfigurer -> httpSecurityRememberMeConfigurer
- .alwaysRemember(true) // "기억하기(remember-me)" 매개변수가 설정되지 않았을 때에도 쿠키가 항상 생성되어야 하는지에 대한 여부를 나타낸다
checkbox에 체크를 하고 → 진행해야 함 (true)로 설정 
- .tokenValiditySeconds(3600) // 토큰이 유효한 시간(초 단위)을 지정할 수 있다
- .userDetailsService(userDetailService) // UserDetails 를 조회하기 위해 사용되는 UserDetailsService를 지정한다
- .rememberMeParameter("remember") // 로그인 시 사용자를 기억하기 위해 사용되는 HTTP 매개변수이며 기본값은 'remember-me' 이다
- .rememberMeCookieName("remember") // 기억하기(remember-me) 인증을 위한 토큰을 저장하는 쿠키 이름이며 기본값은 'remember-me' 이다
- .key("security") // 기억하기(remember-me) 인증을 위해 생성된 토큰을 식별하는 키를 설정한다

RememberMeAuthenticationFilter

SecurityContextHolder에 Authentication이 포함되지 않은 경우 실행 (인증범위를 session / 유효범위 내 하기 위함) / 인증이 유지 되면 이미 인증을 받은 경우이기 때문에 이 기능이 필요 없음

세션이 만료, 애플리케이션 종료, 인증 상태 소멸, 토큰 기반 인증을 사용, 유효성 검사, 토큰 검증되면 자동 로그인

RememberMeAuthenticationFilter → Authentication ≠ null → Y → chin.doFitler //인증을 받지 못한 경우

<사용자와 권한 정보를 갖고와서 토큰을 가져와서 수행>
//인증을 받은 경우 → Authentication ≠ null → N →
RememberMeSevice.autoLogin → RememberMeAuthentication token → AuthenticationManager → 인증 성공 → Y → RememberMeAuthenticationToken → SecurityContextHolder (Authentication을 SecurityContext에 설정) → SecurityContextRepo(세션에 SecurityContext 저장) → ApplicationEvenPublisher
→ Authentication ≠ null → N →
RememberMeSevice.autoLogin → RememberMeAuthentication token → AuthenticationManager → 인증 성공 → N → RemembeMeSevices → loginFail (쿠키 지움)

profile
개발자를 향해 가는 중입니다~! 항상 겸손

0개의 댓글