seok의 패치노트
[Security] JWT - JWT를 이용한 인증처리 프로젝트2 본문
https://oneseok.tistory.com/71?category=933442
[Security] JWT - JWT를 이용한 인증처리 프로젝트2
https://oneseok.tistory.com/70 [Security] JWT - JWT를 이용한 인증처리 프로젝트1 지난 시간까지 이 프로젝트를 만들기 전에 이론적인 내용을 공부해 보았다. RSA를 통한 서명 처리나 HMAC을 이용한 인증처리
oneseok.tistory.com
지난 시간에는 회원가입 처리 및 로그인 관련 파일들을 만들었다.
하지만 formLogin 방식을 사용하고 있지 않기 때문에 "/login" 요청이 자동으로 활성화가 되지 않아 PrincipalDetailsService 가 동작하지 않고있다.
이번시간에는 PrincipalDetailsService 동작을 위한 필터를 만들 것이다.
1. 스프링 시큐리티 필터 체인
아래 사진과 같이 스프링 시큐리티에는 여러 필터들이 연결되어있다.
이번 JWT 토큰인증방식을 구현하기 위해서 "UsernamePasswordAuthenticationFilter" 와 "BasicAuthenticationFilter" 를 상속받은 클래스를 만들것이다.
- 스프링 시큐리티의 인증 순서
- 사용자의 요청을 UsernamePasswordAuthenticationFilter(AuthenticationFilter) 가 가로챈다.
- UsernamePasswordAuthenticationFilter 는 사용자의 요청정보를 토대로 UsernamePasswordAuthenticationToken을 생성후 이걸 이용하여 인증용 객체인 Authentication을 생성한다.
- 인증을 위해 AuthenticationManager에게 인증용 객체 Authentication 을 전달한다.
- AuthenticationManager는 인증을 위해 AuthenticationProvider에게 Authentication 객체를 전달한다.
- AuthenticationProvider는 PrincipalDetailsService(UserDetailService) 에게 인증객체의 username을 넘겨 PrincipalDetails(UserDetails) 객체를 요구한다.
- PrincipalDetailsService는 username으로 DB에서 회원정보를 찾아 PrincipalDetails로 만든다.
- PrincipalDetailsService는 PrincipalDetails를 반환한다.
- AuthenticationProvier는 Authentication과 PrincipalDetails를 가지고 인증을 수행하여 인증 성공시에 Authentication을 반환한다. (이때 반환되는 Authentication 에는 권한 , 인증 여부가 포함되어있다.)
- AuthenticationManager는 AuthenticationProvier를 통해 인증에 성공한 Authentication 객체를 전달받아 반환함
- 인증된 Authentication 객체를 SecurityContextHolder에 담아 성공 시 AuthenticationSuccessHandler 를 호출하고 실패시에는 AuthenticationFailureHandler를 실행한다.
2. UsernamePasswordAuthenticationFilter를 상속받은 필터클래스 만들기
- 필터를 상속받은 클래스를 만들자
- 이 필터는 "/login" url로 요청이 오면 동작한다.
- 이 필터는 로그인 인증을 위한 필터이다.
//json 방식으로 전송한걸 받을때
ObjectMapper om = new ObjectMapper();
//request.getInputStream() 에는 사용자가 전달한 json 데이터가 들어있고 readValue메소드를 통해 매핑된다.
User user = om.readValue(request.getInputStream(), User.class);
//인증을 위한 Authentication 객체를 만들기위해 UsernamePasswordAuthenticationToken 토큰을 생성한다.
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
//실질적인 인증처리를 담당한다.
//authenticationManager 로 로그인 시도를 하게되면 "PrincipalDetailsService" 의 "loadUserByUsername" 가 호출된다.
//로그인 시도가 정상적으로 이루어지면 인증된 Authentication 객체가 넘어오게된다,
Authentication authenticate = authenticationManager.authenticate(authenticationToken);
//시큐리티의 권한관리 로직을 편하게 이용하기 위해 PrincipalDetails 객체를 시큐리티 세션 영역에 넣기 위해 꺼낸다.
//JWT 토큰 방식을 사용하게 되면 세션방식은 사용하지 않아도 되지만 권한관리를 편하게 하기 위해 썼다.
PrincipalDetails principalDetails = (PrincipalDetails) authenticate.getPrincipal();
//리턴이 되면 인증이 완료된 authentication 객체가 자동으로 시큐리티 세션 영역에 저장이된다!!..
//세션이 계속 쌓이면 어떡하나 걱정스럽겠지만 일정 시간이 지나면 세션은 사라지게 되니 괜찮다.
return authentication
- 필터 등록하기
- 파라미터인 authenticationManager객체는 WebSecurityConfigurerAdapter가 가지고 있다.
3. JWT 설정
- jwt 토큰 발급 로직 작성
- JwtAuthenticationFilter 클래스에 이어서 작성하면되고 "successfulAuthentication" 메소드를 재정의할 것이다.
- successfulAuthentication 메소드는 위에 attemptAuthentication 메소드에서 인증이 정상적으로 이루어 졌다면 이어서 자동으로 호출이된다!!
- payload 부분에는 간단하게 pk id와 username 정도만 넣고 signiture 부분에서 HMAC SHA512 알고리즘을 사용하여 secret-key와 함께 암호화 처리를 한다.
- jwt 발급은 헤더로 response 한다.( {"Authorization": "Bearer <token>"} )
4. 권한처리 필터 생성하기
권한이나 인증이 필요한 특정 주소를 요청했을때 시큐리티 필터중 BasciAuthenticationFilter 를 타게 되어있다 이 필터를 상속받아 확장클래스를 만들어 처리하는 로직을 작성할 것이다.
- 권한,인증 처리 필터 클래스 생성하기
- SecurityConfig에 필터 등록하기
- 인증처리를위한 doFilterInternal 메소드 재정의하기
- 현재 모든 요청에대해 이 메소드가 호출되게 되어있다 그래서 이곳에서 토큰값 여부에 따라 인증처리를 진행해주면된다.
- 만약 Authentication 객체를 만들어 SecutiryContextHolder 영역에 저장하는 방법을 사용하지 않는다면 인터셉서를 통해 권한별로 걸러내는 작업을 따로 해줘야할 것이다(왠만하면 그냥 시큐리티에게 권한관리는 맡기자 , 편하니깐..)
5. 권한이 필요한 url 요청해보기
- PostMan을 이용하여 "/api/v1/user" 를 요청해보기
- "/api/v1/manager" , "/api/v1/admin" 요청해보기
* 현재 로그인한 user의 권한이 "ROLE_USER" 이기 때문에 403 권한에러가 나타난다.
6. 토큰 위변조 테스트
- 발급받은 토큰을 JWT 홈페이지에서 변경하여 요청해보자
* HMAC SHA512 알고리즘을 통해 확인해 보았더니 서명이 일치하지 않는다는 익셉션을 발생키는걸 확인 할 수있다!!
'Spring > Security' 카테고리의 다른 글
[Security] 동시세션 제어 (0) | 2021.12.28 |
---|---|
[Security] AnonymouseFilter - Guest 유저를 위함 (0) | 2021.12.28 |
[Security] JWT - JWT를 이용한 인증처리 프로젝트2 (0) | 2021.12.09 |
[Security] JWT - JWT를 이용한 인증처리 프로젝트1 (0) | 2021.12.09 |
[Security] JWT - 이해하기 3(JWT란) (0) | 2021.12.09 |