포스트

2023-03-07-TIL

2023-03-07-TIL

Today I Learned

Spring Boot JWT Authorization and Authentication

JWT(JSON Web Token)는 RFC 7519가 정의한 “두 당사자 사이에 클레임(claim)을 전달하기 위한 간결하고 URL에 안전한 표현”이다. 보통 서명된 JWS 형식으로 쓰고, 점으로 구분된 헤더.페이로드.서명 세 부분을 Base64URL로 인코딩한다. 페이로드에는 RFC가 등록해 둔 iss(발급자), sub(주체), aud(대상), exp(만료 시각), nbf, iat(발급 시각), jti(토큰 ID) 클레임과 애플리케이션이 정한 클레임을 담는다. 서명은 내용이 위조되지 않았음을 보장할 뿐 암호화가 아니므로, 페이로드에 민감한 정보를 넣으면 안 된다.

서버가 세션을 저장하지 않아도 토큰만으로 사용자를 확인할 수 있다는 것이 장점이다. 반대로 한 번 발급한 토큰은 만료 전까지 서버가 강제로 무효화하기 어려워서, 액세스 토큰의 수명을 짧게 두고 리프레시 토큰으로 재발급하는 구성을 많이 쓴다.

  • https://www.freecodecamp.org/news/how-to-setup-jwt-authorization-and-authentication-in-spring/
  • https://medium.com/javarevisited/jwt-and-social-authentication-using-spring-boot-90e4faaa9204
  • https://blog.iamprafful.com/spring-boot-rest-api-authentication-best-practices-using-jwt-2022
  • https://iamprafful.medium.com/spring-boot-rest-api-authentication-best-practices-using-jwt-2022-fd3d7ab61d3
  • https://auth0.com/blog/spring-boot-authorization-tutorial-secure-an-api-java/

Spring Security with JWT for REST API

Toptal 글은 REST의 무상태(stateless) 원칙에서 출발한다. 서버가 클라이언트 상태를 기억하지 않아야 하므로 세션 쿠키 대신 토큰으로 인증하는 방식이 이 원칙에 맞는다는 것이다. Spring Security에서 직접 구현할 때의 흐름은 대체로 같다.

  1. 로그인 요청을 받아 사용자 인증에 성공하면 JWT를 발급한다.
  2. 이후 요청은 Authorization: Bearer <토큰> 헤더로 토큰을 보낸다.
  3. 필터 체인에 추가한 JWT 필터(OncePerRequestFilter 등)가 토큰의 서명과 만료를 검증하고, 성공하면 Authentication 객체를 SecurityContextHolder에 넣는다.
  4. 세션 정책은 STATELESS로 두어 서버 세션을 만들지 않는다.

토큰 발급을 별도 인가 서버가 맡는다면 직접 필터를 짜지 않아도 된다. Spring Security의 OAuth 2.0 Resource Server 지원은 spring.security.oauth2.resourceserver.jwt.issuer-uri만 지정하면 인가 서버의 공개 키를 찾아 Bearer 토큰을 검증한다.

  • https://www.toptal.com/spring/spring-security-tutorial
  • https://www.java67.com/2017/12/top-5-spring-security-online-training-courses.html
  • https://www.bezkoder.com/spring-boot-jwt-authentication/
  • https://medium.com/swlh/stateless-jwt-authentication-with-spring-boot-a-better-approach-1f5dbae6c30f
  • https://www.toptal.com/spring/spring-security-tutorial
  • https://www.toptal.com/java/rest-security-with-jwt-spring-security-and-java
  • https://bootify.io/spring-rest/rest-api-spring-security-with-jwt.html
  • https://www.baeldung.com/spring-security-oauth-jwt
  • https://dzone.com/articles/spring-boot-security-json-web-tokenjwt-hello-world

@JsonView

같은 모델을 클라이언트나 상황에 따라 다른 필드 조합으로 내보내야 할 때, 용도마다 DTO를 따로 만드는 대신 Jackson의 @JsonView를 쓸 수 있다. 뷰는 클래스(보통 빈 인터페이스)로 식별하고, 필드에 어느 뷰에 속하는지 표시한 뒤 직렬화할 때 뷰를 고른다. Javadoc에 따르면 뷰는 클래스 상속 관계를 따르므로 하위 뷰는 상위 뷰의 필드를 모두 포함한다. 스프링 MVC에서는 컨트롤러 메서드에 @JsonView를 붙이면 그 뷰로 응답이 직렬화된다.

1
2
3
4
5
6
7
8
9
10
11
12
public class Views {
    public interface Public {}
    public interface Internal extends Public {}
}

public class User {
    @JsonView(Views.Public.class)
    private String name;

    @JsonView(Views.Internal.class)
    private String email;
}

필드가 많아지면 어떤 필드가 어떤 응답에 나가는지 한눈에 보기 어려워지므로, 응답 형식이 크게 다르면 별도 DTO가 더 명확할 수 있다.

  • https://www.linkedin.com/pulse/jackson-jsonview-its-meaningful-use-spring-boot-rest-amit-patil

연동과 연계

프로젝트에서 섞어 쓰는 두 용어의 차이를 정리한 글들이다. beyondj2ee의 글은 “연동”을 System Link, 즉 WAS와 MySQL, 서비스와 트위터처럼 두 시스템을 일대일로 연결하는 것으로 본다. “연계”는 System Integration으로, 여러 시스템 사이의 연동을 묶어 하나의 업무 흐름을 처리하는 더 큰 개념이다. 예를 들어 온라인 등본 조회에서 게이트웨이, 동사무소 시스템, 이력 저장소 사이의 개별 연결은 연동이고, 이 전체 흐름을 처리하는 것이 연계이며, 이를 맡는 게이트웨이나 EAI, ESB를 연계 시스템이라고 부른다. 글은 업계마다 쓰는 말이 다르니 프로젝트 구성원끼리 용어부터 맞추라고 조언한다. 브런치 글은 지금 접속되지 않는다.

  • https://brunch.co.kr/@pubjinson/13
  • https://www.tumblr.com/beyondj2ee/20532733674/%EC%97%B0%EB%8F%99-%EA%B3%BC-%EC%97%B0%EA%B3%84%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90
참고한 자료외부 출처 4

외부 출처

이 글은 저작권자의 CC BY 4.0 라이선스를 따릅니다.

댓글

아직 댓글이 없습니다