Skip to content

feat: OAuth로그인, JWT 토큰 생성 #8

Open

Description

@yeongleej

어떤 기능인가요?

  • OAuth와 Spring Security를 적용한 로그인 기능 생성
  • JWT를 통한 인증 및 권한부여

작업 상세 내용

  • OAuth 로그인 구현
  • SpringSecurity 적용
  • JWT 토큰 생성
  • 백엔드 로그인 성공시, 리다이렉션 처리 리팩토링
  • 프론트와 연동 - JWT토큰 전달 상세 구현
  • JWT 토큰 유효성 검사
  • 로그아웃 기능 구현
  • 로그아웃 시 블랙리스트 토큰 관리

참고할만한 자료(선택)

Activity

  1. yeongleej commented on Dec 29, 2024

    @yeongleej
    ContributorAuthor

    2024.12.29

    진행 내용

    • Spring Security + OAuth(구글) 적용
    • JWT 토큰 생성
    • OAuth Login SuccessHandler 프론트로 리다이렉트

    ✔️ Google 소셜로그인 CORS

    • 이슈 : Google Oauth CORS
      image

    • 원인

      http://localhost:8080/oauth2/authorization/google에서 리다이렉트된 경로인, http://account.google.com의 XMLHttpRequest에 대한 엑세스가 CORS정책에 의해 차단됨. Access-Controller-Allow-Origin 헤더가 요청에 존재하지 않는다.

    • 해결

      • window.location.href 방식 사용
      • axios와 window.location.href의 차이
        (1) axios : AJAX 요청을 통해 서버와 데이터를 비동기적으로 주고받음
        • 이러한 요청은 브라우저의 CORS 정책에 의해 제어됨 -> 서버가 Access-Control-Allow-Origin 헤더를 포함하지 않으면, 브라우저는 요청 결과를 클라이언트에게 전달하기 전에 차단하며, CORS 에러를 발생시킴
          (2) window.location.href : 브라우저가 페이지를 이동하거나 리다이렉트하도록 지시
        • 이 방식은 브라우저가 서버에 HTTP GET 요청을 보내고, 리소스를 받아와 현재 페이지를 대체함 -> 브라우저가 리소스를 가져오는 과정에서는 CORS 정책이 적용되지 않음!
        • 즉, 리소스가 동일 출처인지 상관없이 페이지 이동은 허용됨 -> 이는 브라우저의 CORS 정책이 AJAX 요청과 같은 프로그램적 데이터 요청에만 적용되기 때문

    참고: https://hyun-jng.tistory.com/entry/WEB-OAuth2%EB%A1%9C-google%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B5%AC%ED%98%84-%EC%A4%91-%EC%A7%81%EB%A9%B4%ED%96%88%EB%8D%98-CORS%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0

    앞으로 해야할 일

    • Spring Security 및 Controller 요청 리팩토링
    • 로그아웃 구현 & JWT 토큰 관리
  2. yeongleej commented on Jan 9, 2025

    @yeongleej
    ContributorAuthor

    2025.01.09

    진행 내용

    • 프론트에서 JWT 토큰 전달
    • 프론트에서 전달한 JWT 토큰 유효성 검사(Authentication) 및 예외처리 핸들러 등록

    ✔️ Spring Security Authentication(인증) 예외 핸들러

    image

    • AuthenticationEntryPoint → 인증되지 않은 사용자의 접근을 차단 (401)
      • jwt가 없거나, 인증되지 않은 사용자(만료된 토큰, 블랙리스트 토큰, 토큰의 일부가 사라짐 등)가 보호된 리소스에 접근할 때 실행
    @Component
    public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
    
        @Override
        public void commence(HttpServletRequest request, HttpServletResponse response, 
                             AuthenticationException authException) throws IOException, ServletException {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401 상태 코드
            response.setContentType("application/json");
            response.getWriter().write("{\"error\": \"Unauthorized\", \"message\": \"인증이 필요합니다.\"}");
        }
    }
    • AccessDeniedHandler → 인증은 되었지만, 권한이 없는 경우 차단 (403)
      • 인증된 사용자가 권한이 없는 리소스를 요청했을 때 실행
    @Component
    public class JwtAccessDeniedHandler implements AccessDeniedHandler {
    
        @Override
        public void handle(HttpServletRequest request, HttpServletResponse response, 
                           AccessDeniedException accessDeniedException) throws IOException, ServletException {
            response.setStatus(HttpServletResponse.SC_FORBIDDEN); // 403 상태 코드
            response.setContentType("application/json");
            response.getWriter().write("{\"error\": \"Forbidden\", \"message\": \"권한이 부족합니다.\"}");
      
    • security filter에 적용
    ... 
    http
                .exceptionHandling(exception -> exception
                    .authenticationEntryPoint(jwtAuthenticationEntryPoint) // 인증 예외 처리
                    .accessDeniedHandler(jwtAccessDeniedHandler) // 권한 예외 처리
                );

    Exception 처리 맨날 모르는척 했다가 이번에 제대로 공부해야겠다고 다짐했습니다!! ㅎㅎㅎ히 😄

    앞으로 해야할 일

    • @AuthenticationPrincipal 적용
    • 로그아웃 기능 및 토큰 관리 구현
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions