<TIL> 67. spring security / antMathers vs mvcMatchers

YUJIN LEE·2023년 3월 20일
0

개발log

목록 보기
62/149

antMatchers("/test")

-> 정확한 /test URL만 일치.

mvcMatchers("/test")

-> /test, /test/, /test.html/, /test.xyz 등 다양하게 일치

spring security

스프링 시큐리티는 자바 애플리케이션에 인증과 인가를 제공하는 데 중점을 둔 프레임워크
기존 서블릿 필터에서 인증처리 한 것 보다,
custom requirements(맞춤형 요구사항)을 충족시키기 위해 굉장히 쉽게 확장 가능.

필터

필터는 체인처럼 엮어있기 때문에 필터 체인이라고 불리는데, 모든 request는 이 필터 체인을 반드시 거쳐야 한다.

  • spring security는 filter기반으로 동작하기 때문에(AOP) spring MVC와 분리되어 관리 및 동작.

Security 용어

  • 접근 주체(Principal)
  • 보호된 대상에 접근하는 클라이언트
  • 인증(Authentication)
  • 현재 유저가 누구인지 확인 / 애플리케이션의 작업을 수행할 수 있는 주체임을 증명하는 과정
  • 인가(Authorize)
  • 현재 유저가 어떤 서비스, 페이지에 접근할 수 있는 권한이 있는지 검사
  • 권한(Authorization)
  • 인증된 주체가 애플리케이션의 동작을 수행할 수 있도록 허락되있는지를 결정.

spring security는 세션-쿠키 방식으로 인증

  1. 유저가 로그인 시도 (http request)
  2. AuthenticationFilter에서부터 user DB까지 타고 들어감
  3. DB에 있는 유저라면 UserDetails로 꺼내서 유저의 session 생성
  4. spring security의 인메모리 세션저장소인 SecurityContextHolder에 저장
  5. 유저에게 session ID와 함께 응답 내려줌
  6. 이후 요청에서는 요청쿠키에서 JSESSIONID를 까봐서 검증 후 유효하면 Authentication(권한)을 준다.

HttpSecurity

.authorizeRequests() - 요청에 대한 권한 지정 가능
.anyRequest().authenticated() - 인증이 되어야 한다는 이야기
.anonymous() - 인증되지 않은 사용자도 접근할 수 있다.
.fullyAuthenticated() - 완전히 인증된 사용자만 접근할 수 있다.
.hasRole() or hasAnyRole() - 특정 권한을 가지는 사용자만 접근할 수 있다.
.hasAuthority() or hasAnyAuthority() - 특정 권한을 가지는 사용자만 접근 가능
.haslpAddress() - 특정 아이피 주소를 가지는 사용자만 접근할 수 있다.
.access() - SpEL? 표현식에 의한 결과에 따라 접근할 수 있다.
.not() - 접근 제한 기능을 해제
.permitAll() or denyAll() - 접근을 전부 허용하거나 제한한다.
.rememberMe() - 로그인한 사용자만 접근할 수 있다. 리멤버 가능 -> 단순히 아이디나 토큰을 기억하는게 아니라 로그인 정보를 유지하는 방법.

UserDetails & UserDetailsService

스프링 시큐리티는 사용자 정보를 UserDetails 구현체로 사용.
그래서 스프링 시큐리티는 User라는 클래스 제공.

하지만 이름과 패스워드 권한들에 대한 필드만 있음.
이메일 정보나 프로필 이미지 경로 등과 같은 부가적인 정보는 담을 수 없다.

따라서 UserDetails 구현체를 직접 만들어야함.

AuthenticationSuccessHandler &

AuthenticationFailureHandler

클라이언트가 인증과정을 성공했을때와 실패했을 경우 Handler를 implementation해서 custom 가능

spring security 내부 구조

  • SecurityContextHolder
    - SecurityContextHolder는 SecurityContext를 제공하는 static메소드(getContext)를 지원
  • SecurityContext
    - SecurityContext는 접근 주체와 인증에 대한 정보를 담고 있는 Context.
    즉, Authentication을 담고있다.
  • Authentication
    - Principal과 GrantAuthority를 제공. 인증이 이루어지면 해당 Authentication 저장
  • Principal
    - 유저에 해당되는 정보 , 대부분의 경우 Principal로 UserDetails 반환
  • GrantAuthority
    - ROLE_ADMIN, ROLE_USER 등 Principal이 가지고 있는 권한을 나타낸다.

인증처리순서

  1. 처음 요청이 들어오면 AuthenticationFilter(UsernamePassAuthenticationFilter)를 거친다.
  2. 요청에 따른 UsernamePasswordAuthenticationToken을 생성.
    (Authentication 인터페이스의 구현체다.)
  3. UsernamePasswordAuthenticationToken(통상 Token이라고 하겠다)을
    AuthenticationManager에게 이 Token은 올바른 유저인지 물어본다.
  4. AuthenticationManager는 1개 이상의 AuthenticationProvider(통상 A-Provider)를 갖고있는데, A-Provider는 Token 객체를 적절히 판단하여 인증처리를 하려고 함.
  5. A-Provider가 우리가 직접 구현한 서비스(UserDetailsService 구현 클래스)에 해당 유저에게 인증 요청을 보내 사용자 정보를 가져온다.
  6. UserDetailsService 구현 클래스는 사용자 정보를 가져와 UserDetails를 반환
  7. Provider는 UserDetailsService에서 반환된 UserDetails와 클라이언트가 제공한 인증정보(Token)을 대조해서 이용자가 정당한 사용권한을 가지고 있는지 확인, 그리고 SecurityContext에 저장

*** WebSecurityConfigurerAdapter를 상속받는 클래스에 @EnableWebSecurity어노테이션을 선언하면 SecurityFilterChain이 자동으로 포함됨.
WebSecurityConfigurerAdapter를 상속받아서 메서드 오버라이딩을 통해 보안 설정을 커스터마이징하는 것이 SpringSecurity의 핵심적인 일.

주요 객체

  • AuthenticationManager
    인증 요청을 받고 Authentication을 채움.
    유저의 request가 담긴 Authentication을 AuthenticationManager에 넘겨주고,
    AuthenticationManager를 구현한 ProviderManager가 처리.
    정확히는 ProviderManager는 private List provider; 로 여러 AuthenticationProvider를 가질 수 있는데, 이것들이 처리를 해서 Authentication를 반환해준다.(실패하면 예외를 던짐)

  • AuthticationProvider
    실제 인증이 일어나며, 성공하면 Authentiction.isAuthenticated = true 함.

  • Authentication
    모든 접근 주체(=유저)는 Authentication 생성.
    이것은 SecurityContext에 보관되고 사용.
    즉, security의 세션들은 내부 메모리(SecurityContextHolder)에 쌓고 꺼내쓰는 것.
    Authentication 인터페이스에 상속받는 UserDetails 인터페이스가 중요한 이유.

PasswordEncoder

BcryptPasswordEncoder

Bcrypt 해시 함수를 사용한 PasswordEncoder.
Bcrypt는 애초부터 패스워드 저장을 목적으로 설계
password를 무작위로 여러번 시도해 맞추는 해킹을 방지 위해 암호를 확인할 때 의도적으로 느리게 설정.
BcryptPasswordEncoder는 강도를 설정할 수 있는데 강도가 높을수록 오랜 시간이 걸린다.

profile
인정받는 개발자가 되고싶습니다.

0개의 댓글