아델
688
2020-10-04 16:56:07 작성 2020-10-04 16:56:35 수정됨
2
142

요청 응답의 헤더 값을 자동으로 요청에 포함하고 싶습니다


로그인 하면 응답 헤더로 JWT를 전달해 주고싶습니다




보호받는 URL을 요청할때는 헤더에 JWT를 전달해줘야 합니다


현재 Post-man으로 헤더값을 직접넣어주고 있지만

Client가 요청할때 헤더에 JWT값을 포함해야 되는데 그 방법을 잘모르겠습니다


전달받은 JWT를 쿠키에 넣으면 Client 요청에 넣을수 있는데 최선의 방법은 아니라고 판단되어서 

질문 올립니다


아래는 토큰을 검증하는 스프링 시큐리티 필터 코드 입니다



@RequiredArgsConstructor
@Log4j2
public class JwtTokenVerifier extends OncePerRequestFilter {

    private final UserAPI userAPI;

    // UserAPI에게 토큰 검증을 요구하자
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        String authorizationHeader = request.getHeader("X-AUTHORIZATION-TOKEN");
        log.info(authorizationHeader);
        if (Strings.isNullOrEmpty(authorizationHeader) || !authorizationHeader.startsWith("Bearer ")) {
            filterChain.doFilter(request, response);
            return;
        }
        String token = authorizationHeader.replace("Bearer ", "");

        try {
            String username = userAPI.parseToken(token);

            Authentication authentication = new UsernamePasswordAuthenticationToken(username, null, null);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        // 토큰 검증 실패 로직
        catch (JwtException e) {
            throw new IllegalStateException("Token %s cannot be trusted");

        }
        filterChain.doFilter(request, response); // 다음 단계로 전달
    }



0
  • 답변 2

  • RWB
    351
    2020-10-04 17:35:49 작성 2020-10-04 17:39:22 수정됨

    제가 이해한 것이 맞다면


    로그인

    요청: 사용자 로그인 -> 응답: 지정한 헤더로 JWT값 클라이언트에 전달


    인증이 필요할 경우

    요청: 헤더에 유효한 JWT를 담아서 전송 -> 응답: JWT 검증결과에 따른 프로세스 진행


    이런 식으로 설계하신다는 말씀같은데...


    보통 JWT를 쓰는 이유는 Payload에 서버가 의도한 다양한 정보를 담을 수 있으면서도, 비/대칭키를 활용한 높은 암호화에 용이하면서도 이를 클라이언트에 저장함으로써 서버에 부담을 주지 않기 때문입니다.

    로그인을 구현하는 대표적인 방법이 세션과 쿠키인데, 세션의 경우 보안성이 뛰어나지만 서버의 자원을 요구한다는 단점이 있고, 쿠키의 경우 클라이언트가 직접 접근이 가능하므로 보안성이 약하다는 단점이 있습니다.


    JWT의 특징에 의거하면, 서버에 JWT와 관련된 내용을 서버에 유지하는 것 자체가 JWT의 의의에 반하는 일입니다. 즉, JWT는 클라이언트가 갖고 있을 때 그 의의가 커집니다.

    문제는 클라이언트가 들고 있다는 말은 클라이언트가 상대적으로 쉽게 접근이 가능하다는 뜻이고, 질문자분 역시 이러한 문제로 인해 질문을 주신 것 같은데...


    어찌됐든 요청값에 JWT를 포함하기 위해선 어떠한 방법으로든 클라이언트가 JWT를 갖고 있으면서 요청시 사용해야 합니다. 이를 구현하는 가장 편한 방법이 쿠키인거죠.

    만약 질문자분이 쿠키는 사용자가 접근하여 변조할 수 있으니 싫다고 하시면, 페이지 이동 시나 요청값의 초기화, 변경이 유발되는 시점마다 클라이언트 단계에서 JWT를 유지할 수 있는 방법을 강구하셔야 합니다.

    DB와 같은 다른 요소를 이용하지 않는다면, 순수 JS만으로 해결을 보셔야하는데, 아시겠지만 JS 역시 마찬가지로 클라이언트 단계이므로 구조만 알면 얼마든지 사용자 단계에서 접근이 가능해요.

    [클라이언트 단계에서 JWT를 보관할 수 있는 방법]을 구현하면 만사 OK인데, 이를 가장 쉽게 구현한 것이 쿠키입니다.


    위 방법만 구현하신다면 요청 헤더에 값을 넣는건 쉽습니다. 요청 시, 요청 객체를 전달받아 특정 헤더에 특정 값만 넣어주시면 끝나는 문제라서요.


    질문에 대한 해답도 좋겠지만, 제 생각엔 여기는 쿠키로 구현하고 다른 기능에 시간을 투자하는 것도 나쁘지 않아보입니다.

    해당 쿠키의 만료시간을 -1로 설정하면, 브라우저를 종료할 시 쿠키가 자동으로 제거되어 JWT값을 날아가게 하거나, JWT 자체에 만료시간을 지정할 수도 있습니다.

    보통 JWT 구현에 auth0나 io.webtoken과 같은 라이브러리를 많이 사용하실텐데, 아시다시피 대부분의 JWT 라이브러리에는 검증 함수를 제공하며, 검증 시 암호화 키와 만료시간 등을 체크하여 문제가 있을 경우 예외를 발생시킵니다.

    또한, JWT는 서버 상에서 임의의 키로 암호화가 되어있어, 해당 키를 알고 있어아먄 JWT를 변조할 수 있습니다. 이를 탈취한다 하더라도, 해당 인증정보를 이용하거나 삭제함으로써 인증정보를 없어는 정도입니다.

    인증정보를 탈취해 인증에 사용하는 경우, 만료시간을 짧게 두고 Refresh JWT를 통해 이를 타개할 수 있습니다. 물론 만료시간 이전에 접근할 경우라는 헛점이 존재하지만, 클라이언트에 보관을 전가하는 JWT의 특성 상 나타나는 구조적 한계입니다.


    질문자분의 걱정을 덜기 위해 JWT에는 보안을 위해 개발자들이 고안한 여러 보완점을 제공하니, 쿠키를 사용하시되, 위와 같이 보안을 좀 더 강화하는 측면이 효과적일 것 같습니다.

  • 아델
    688
    2020-10-04 18:08:22

    RWB

    긴 글 감사합니다

  • 로그인을 하시면 답변 을 등록할 수 있습니다.