Spring Security JWT - JWT를 통한 인증
JWT 검증
JwtAuthorizationFilter 클래스 생성
public class JwtAuthorizationFilter extends BasicAuthenticationFilter {
private UserRepository userRepository;
public JwtAuthorizationFilter(AuthenticationManager authenticationManager, UserRepository userRepository) {
super(authenticationManager);
this.userRepository = userRepository;
}
@Override
/** 인증이나 권한이 필요한 주소요청이 있을 때 실행되는 메서드 */
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("인증이나 권한이 필요한 주소 요청");
String jwtHeader = request.getHeader("Authorization");
System.out.println("jwtHeader : " + jwtHeader);
/* 클라이언트 측에서 전달받은 JWT가 올바른지 확인 */
if (jwtHeader == null || !jwtHeader.startsWith("Bearer")) {
chain.doFilter(request, response);
return;
}
/* 클라이언트 측에서 전달받은 JWT 검증 */
String jwtToken = request.getHeader("Authorization").replace("Bearer ", "");
String username = JWT.require(Algorithm.HMAC512("qlsdud0604")).build().verify(jwtToken).getClaim("username").asString();
/* JWT 검증이 올바르게 된 경우 */
if (username != null) {
User userEntity = userRepository.findByUsername(username);
PrincipalDetails principalDetails = new PrincipalDetails(userEntity);
Authentication authentication = new UsernamePasswordAuthenticationToken(principalDetails, null, principalDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication); // 시큐리티 세션 공간에 Authentication 저장
chain.doFilter(request, response);
}
}
}
ㆍ 로그인을 한 사용자가 권한이 필요한 페이지에 접근을 할 때 해당 사용자의 JWT를 이용한 인증 과정이 필요하다
ㆍ 해당 과정을 처리하는 클래스인 JwtAuthorizationFilter 클래스를 jwt 패키지 내에 생성하고 BasicAuthenticationFilter 클래스를 상속받는다.
ㆍ BasicAuthenticationFilter 클래스는 시큐리티가 가지고 있는 필터 중 하나이며, 권한이나 인증이 필요한 특정 주소에 접근했을 때 해당 필터를 반드시 거치게 된다.
ㆍ doFilterInternal() 메서드에서는 클라이언트 측으로부터 전달받은 JWT를 검증하는 코드가 들어간다.
ㆍ JWT의 검증이 정상적으로 완료가 되면 클라이언트는 권한이 필요한 주소에 접근이 가능해진다.
JwtAuthorizationFilter 필터 등록
ㆍ JwtAuthorizationFilter 클래스가 필터의 역할을 수행하기 위해서는 시큐리티 필터에 등록을 해야 한다.
ㆍ SecurityConfig 클래스에 UserRepository 객체를 선언하고 .addFilter() 메서드를 이용해서 JwtAuthorizationFilter 클래스를 시큐리티 필터에 등록한다.
RestApiController 클래스 수정
/* user, manager, admin 권한 접근 가능 */
@GetMapping("/api/v1/user")
public String user() {
return "user";
}
/* manager, admin 권한 접근 가능 */
@GetMapping("/api/v1/manager")
public String manager() {
return "manager";
}
/* admin 권한 접근 가능 */
@GetMapping("/api/v1/admin")
public String admin() {
return "admin";
}
ㆍ JWT 인증을 테스트하기 위해 RestApiController 클래스에 위 메서드들을 추가한다.
ㆍ 각 메서드들과 매핑된 주소에 접근하기 위해서는 서로 다른 권한이 요구된다.
테스트
로그인 요청
ㆍ username의 값을 "qlsdud0604"로 password의 값을 "1234"로 지정한 후 JSON 형태로 로그인 요청을 한다.
Header 정보 확인
ㆍ 로그인 요청을 한 후 서버 측에서 발급한 JWT 정보를 Header를 통해 확인한다.
"/api/v1/user" 주소 접근
ㆍ 로그인이 된 상태에서 서버로부터 발급받은 JWT를 Header에 포함하여 "/api/v1/user" 주소에 접근한다.
ㆍ ROLE_USER 권한을 가진 사용자는 해당 주소에 접근이 가능한 것을 확인할 수 있다.
"/api/v1/manager" 주소 접근
ㆍ 로그인이 된 상태에서 서버로부터 발급받은 JWT를 Header에 포함하여 "/api/v1/manager" 주소에 접근한다.
ㆍ ROLE_USER 권한을 가진 사용자는 해당 주소에 접근이 불가능한 것을 확인할 수 있다.
"/api/v1/admin" 주소 접근
ㆍ 로그인이 된 상태에서 서버로부터 발급받은 JWT를 Header에 포함하여 "/api/v1/admin" 주소에 접근한다.
ㆍ ROLE_USER 권한을 가진 사용자는 해당 주소에 접근이 불가능한 것을 확인할 수 있다.
GitHub - qlsdud0604/spring-security-basic: 스프링 시큐리티의 기초를 학습하는 공간
스프링 시큐리티의 기초를 학습하는 공간. Contribute to qlsdud0604/spring-security-basic development by creating an account on GitHub.
github.com