inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

스프링부트 시큐리티 & JWT 강의

안녕하세요 ! 질문이 있습니다.

446

오세창

작성한 질문수 8

0

강사님의 강의를 통해 Jwt 와 시큐리티에 대한 공부를 수월히 할 수 있었습니다.

근데 개인적으로 이제 실습하면서 문제가 발생해서 자문을 구하고자 글을 쓰게 되었습니다.

 

로그인이 성공하면 토큰을 로컬 스토리지에 담고, 요청할 때는 토큰을 꺼내어 헤더에 담아서 검증절차를 진행하려고 합니다.

 

근데 분명 위의 프로세스에 해당 하는 로직을 작성하였다고 생각하였는데, 의도한 대로 흘러가지가 않아서 매우 난처한 상황입니다.

 

Index.html

<script>
    $(document).ready(function() {
        // 로그아웃 버튼 이벤트
        $('#logoutButton').click(function() {
            // 로컬 스토리지에서 토큰 제거
            localStorage.removeItem('accessToken');
            // 로그인 페이지로 리다이렉션
            window.location.href = '/login';
        });

        // 테스트 버튼 이벤트
        $('#testButton').click(function() {
            // 로컬 스토리지에서 토큰 가져오기
            const token = localStorage.getItem('accessToken');
            if (token) {
                $.ajax({
                    url: '/api/test', // 요청할 서버의 URL
                    type: 'GET', // HTTP 메서드
                    beforeSend: function(xhr) {
                        // 요청 헤더에 토큰 추가
                        xhr.setRequestHeader('Authorization', token);
                    },
                    success: function(data) {
                        // 요청 성공 시 로직
                        console.log("테스트 요청 성공:", data);
                        alert("테스트 요청 성공");
                    },
                    error: function(xhr, status, error) {
                        // 요청 실패 시 로직
                        console.error("테스트 요청 실패:", xhr.responseText);
                        alert("테스트 요청 실패");
                    }
                });
            } else {
                alert("토큰이 없습니다. 다시 로그인해주세요.");
            }
        });
    });
</script>

 

이와 같이 /url/test 로 api 요청을 할때 헤더에 토큰을 담게 했습니다.

이에 "테스트 버튼"을 누르게 되면

 

JwtAuthorizationFilter

@Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) throws ServletException, IOException {
        // 헤더에서 토큰 추출
        log.info("헤더에서 토큰 추출");
        String tokenValue = jwtUtil.getJwtFromHeader(req);
        log.info("토큰 : " + tokenValue);

        if (StringUtils.hasText(tokenValue)) {

            // 토큰 유효성 검사
            if (!jwtUtil.validateToken(tokenValue)) {
                log.info("Token Error");

                return;
            }
            Claims info = jwtUtil.getUserInfoFromToken(tokenValue);

            try {
                setAuthentication(info.getSubject());
            } catch (Exception e) {
                log.error(e.getMessage());
                return;
            }
        }

        else {
            log.info("토큰이 없습니다.");
        }

        filterChain.doFilter(req, res);
    }

    // 인증 처리
    public void setAuthentication(String loginId) {
        log.info("인증 성공");
        SecurityContext context = SecurityContextHolder.createEmptyContext();
        Authentication authentication = createAuthentication(loginId);
        context.setAuthentication(authentication);

        SecurityContextHolder.setContext(context);
    }

    // 인증 객체 생성
    private Authentication createAuthentication(String loginId) {
        log.info("인증 객체 생성");
        UserDetails userDetails = userDetailsService.loadUserByUsername(loginId);
        return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
    }

 

로그로 토큰이 출력되는 것과 최종적으로 인증 객체 생성까지 되는 것을 확인했습니다.

그러나 이렇게 인가 필터를 거치고 이제 컨트롤러로 접근하게 되면

    @GetMapping("/api/test")
    public String testPage() {
        log.info("test controller");
        return "test";
    }

 

저기 test controller 라는 로그만 찍힌채 프로세스가 마무리됩니다.

 

최종로그

2024-02-26T16:19:36.394+09:00  INFO 60592 --- [nio-8081-exec-9] JWT 검증 및 인가                              : 토큰 : eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0NiIsImF1dGgiOiJPV05FUiIsImlhdCI6MTcwODkzMTk3MywiZXhwIjoxNzA4OTM1NTczfQ.A2AhGDg5phTcm4gGC-01K0jKoAGE1c5Ygsq9v_J1ntk
2024-02-26T16:19:36.426+09:00  INFO 60592 --- [nio-8081-exec-9] JWT 검증 및 인가                              : 인증 성공
2024-02-26T16:19:36.427+09:00  INFO 60592 --- [nio-8081-exec-9] JWT 검증 및 인가                              : 인증 객체 생성
Hibernate: 
    /* <criteria> */ select
        u1_0.id,
        u1_0.email,
        u1_0.login_id,
        u1_0.password,
        u1_0.role 
    from
        users u1_0 
    where
        u1_0.login_id=?
2024-02-26T16:19:36.434+09:00  INFO 60592 --- [nio-8081-exec-9] TestController                           : test controller

 

이때 웹 페이지의 개발자 도구를 열어서 콘솔로그를 확인 해보면, 제가 가지고 오고자 했던 test.html 의 코드만이 적혀있을 뿐입니다.

 

뭐가 문제인 걸까요..

 

혹시나 test 쪽에 토큰을 가져오는 로직도 작성해봤습니다.

 

Test.html

<head>
    <meta charset="UTF-8">
    <script src="https://code.jquery.com/jquery-3.7.0.min.js"
            integrity="sha256-2Pmvv0kuTBOenSvLm6bvfBSSHrUJ+3A7x6P5Ebd07/g=" crossorigin="anonymous"></script>
    <script>
        $(document).ready(function () {
            const auth = getToken();

            if (auth) {
                $.ajaxPrefilter(function (options, originalOptions, jqXHR) {
                    jqXHR.setRequestHeader('Authorization', auth);
                });
            } else {
                window.location.href = '/user/login-page';
            }
        });

        function getToken() {
            let auth = localStorage.getItem('accessToken');
            return auth || '';
        }
    </script>
    <title>Test Page</title>
</head>
<body>
<h1>This is a test page.</h1>
</body>
</html>

 

그럼에도 여전히 해당 페이지에는 접근을 못하고 있습니다 ㅠㅠㅠㅠ

제가 놓친 부분이 뭐가 있을지 조언을 주신다면 감사하겠습니다.

spring spring-security jwt

답변 2

0

최주호

아래 콘솔 로그 확인 해보세요. Bearer 추가해주시고!!

imageimage

0

인프런 AI 인턴

안녕하세요, 인프런 AI 인턴입니다.
모코코님, 스프링 부트와 JWT를 활용한 보안 관련하여 실습 중 문제가 생겨 고민이 많으시군요. 문제를 해결하기 위해 몇 가지 가능성을 살펴보겠습니다.

  1. Authorization 헤더 형식 확인
  • JWT 토큰을 HTTP 헤더에 전달할 때 일반적으로 ‘Bearer’ 접두어를 붙여서 전송합니다. 현재 스크립트에서는 Token 값만 설정하고 있습니다. 형식이 Authorization: Bearer {token}과 같아야 한다는 점을 확인해 주세요.
  1. 서버의 CORS 설정 확인
  • 클라이언트와 서버가 다른 도메인에 있을 경우, 서버측에서 CORS(Cross-Origin Resource Sharing) 정책으로 인해 요청이 차단될 수 있습니다. 서버의 CORS 설정이 올바르게 되어 있는지 확인해야 합니다.
  1. 응답 처리 방식 확인
  • 컨트롤러에서 문자열을 반환할 때, test라는 문자열이 그대로 반환되고 있는 것으로 보입니다. 만약 test.html 페이지를 반환하고자 한다면 Thymeleaf나 JSP와 같은 템플릿 엔진을 사용하고 있지 않는다면, return "redirect:/test.html";과 같이 리다이렉트를 사용하거나 ModelAndView 객체를 사용하여 뷰 이름을 설정하는 방식을 사용해야 합니다.
  1. Security 설정 확인
  • 스프링 시큐리티 설정에서 인증된 사용자만 접근할 수 있는 URL 경로가 올바르게 설정되어 있는지, 인가 과정에서 문제가 없는지도 점검해야 합니다. 컨트롤러에 접근하기 전에 필요한 권한이 제대로 부여되었는지 확인해 보십시오.
  1. 브라우저 콘솔 및 네트워크 탭 확인
  • 브라우저의 개발자 도구에서 콘솔 로그뿐만 아니라 네트워크 탭을 통해 HTTP 요청과 응답에 대한 상세한 정보를 확인해보세요. 요청 헤더, 응답 상태 코드 및 응답 본문 등을 확인하면 문제를 파악하는 데 도움이 됩니다.

위의 가능성들을 하나씩 확인해가며 문제를 해결해보시기를 바랍니다. 추가적으로 필요하다면, 스프링 시큐리티의 테스트 관련 문서를 참고하실 수 있습니다. Spring Security Reference Documentation에서 더 자세한 정보를 얻으실 수 있습니다. 혹시나 설정이나 코드에 더 궁금한 점이 있다면 질문해 주세요.

JWT를 구현한 다음 이 API를 호출해서 사용하는 것은 프론트엔드 쪽에서 하는 역할인가요?

0

98

1

Jwt쓰면 스프링시큐리티는 필수적으로 사용해야하나요?

0

401

1

13:23 system.out 출력문이 다르게 나옵니다.

0

130

1

수료증 문의

0

227

2

9분대에 질문이 있습니다 !

0

115

1

password 비교를 하지 않았는데 어떻게 인증이 통과된 건가요?

0

321

1

이전 강의 참고하라는 말씀

0

253

1

강의 실습하다가 막히는 분들 참고(2024년8월 기준)

2

1116

2

구글 소셜 로그인 302

0

201

1

오류 문의 _ org.springframework.orm.jpa.JpaSystemException: could not deserialize

1

584

1

[자바] 시큐리티 Config 참고

13

953

1

이론강의

0

280

1

SpringSecurity JWT 로그인 URL 2개 설정하는 방법

0

488

1

2024.06기준) 최근 SecurityConfig 설정 문의

0

922

3

구글 로그인시 authentication이 null 값이라고 에러가 발생합니다.

0

678

2

특정 url필터 거는 방법 이슈

0

422

1

강사님께서 말씀하시는 시큐리티세션이 SecurityContext인가요?

0

279

1

25강 마지막 테스트에서 오류

1

1044

2

jwt를 저장하는 위치에 궁금한 점이 있습니다.

0

298

1

mustache를 사용하지 않고 thymeleaf를 사용하려고 하는데

0

697

1

세션 인증방식이 REST 원칙에 위배되는 건가요?

0

342

1

jwt와 실제데이터의 관계

1

244

1

jwt 와 세션ID의 관계

1

313

1

SecurityConfig에서 세션 설정, 인가 설정

0

422

1