문제
컨트롤러에서 토큰 인증만 하고 실제로 있는 유저가 존재하는지 확인하지 않고 진행시키면 문제가 발생할 수 있어 인증 권한이 필요한 테스트일 경우 항상 실제 유저와 일치하는지 확인할 필요가 있다.
현재 인증 과정
- Token이 헤더에 실려서 날라온다.
- 만약 로그인이 필요한 서비스라면 JwtAuthenticationFilter에서 Header를 필터에서 확인하고 만약 헤더가 있다면 UserId를 JwtAuthentication에서 꺼내쓸 수 있다.
- JwtAuthentication에는 userId와 JwtToken이 있다.
핵심
- 문제가 날 수 있는 경우
- Jwt토큰의 유저가 탈퇴한 유저일 경우에도 Controller로 API를 사용 가능하다.
- 만약 라이딩 포스트를 UD할 경우 헤더에 담긴 유저와 수정하는 포스트의 유저가 다르지만 수정을 할 수 있다.
위의 경우들을 어디서 Validation을 하는지가 중요하다. 탈퇴를 전자, UD를 후자라고 정의하자.
만약 전자인 경우에는 jwt토큰에서 받아온 유저의 id가 존재하는지 UserRepository에서 확인해야 한다.
후자인 경우 jwt토큰에서 받은 유저의 id가 존재하는지 확인하고 존재한다면 다시 RidingPost를 UD하는 User와 일치하는지 확인해야 한다.
즉 필수적으로 확인할 것은 jwt토큰에서 받은 유저의 id가 존재하는지 확인해야 한다.
해결 방법
어제 지웠던 UserDetails와 UserDetailsService를 다시 만드는 것이다.
이전에 설정한 AccessDeniendHandler에서 getPrincipal()을 불러오게 되는데 이는 JwtAuthenticationFilter에서 검증한 JwtAuthentcation에서 getPrincipal을 받아오는데 이때 getPrincipal을 위해 설정한게 바로 UserDetails와 UserDetialsService이다.
여기서 getPrincipal은 UserDetails의 정보를 가져오게되고 이 정보들은 UserDetailsService를 통해 가져오게 된다.
AccessDeniedHandler는 서버에 요청을 할 때 액세스가 가능한지 권한을 체크후 액세스 할 수 없는 요청을 했을시 동작된다.
AuthenticationEntryPoint는 인증이 되지않은 유저가 요청을 했을때 동작된다.
둘 중 아무거나 사용해도 상관없지만 이미 AccessDeniedHandler로 만들었기 떄문에 전자를 사용한다.
만약 이게 안된다면 jwt필터에서 UserRepository를 주입받아 확인하는 방법으로 가능하다. 이렇게 되면 필터를 거칠때 항상 jwt토큰이 있을경우 유저레포지토리에서 유저가있는지 확인하기 때문에 UserMe도 없어져도 된다.
즉 UserDetails와 UserDetailsService만 다시 만들어주면 토큰에 userid를 통해 테이블에서 해당 유저가 존재하는지 검증이 가능해진다. 따라서 UserMe에서 AccessDeniedHandler가 동작하는지 검증을 한다면 다른 컨트롤러에서는 토큰이 유효한지만 검증하면 된다.