spring

스프링 시큐리티 JWT 간단 정리 -2

kimkim615 2024. 9. 6. 21:35

8. DB기반 로그인 검증 로직

로그인 요청이 POST 경로로 넘어오면 시큐리티 필터에서 body에 있는 username과 password를 꺼내서 검증하는

토큰 객체를 만들고, 그 객체를 Manager한테 넘겨주는 과정을 진행하였음 여태까지.

실행을 하면 로그인을 검증하는 뒷부분이 완성이 안되어서 오류가 발생했었다 그래서 이제는 뒷부분을 구현할 예정~

 

 

UserRepository

 

 

UserRepository에 해당 유저를 조회하는 쿼리를 만들 것이다 리턴타입은 엔티티를 리턴하고 쿼리는 findByUsername

내부 인자는 username으로 작성하면 됨

이제 UserDetailsService에서 위 메서드를 통해서 특정 유저를 조회할 수 있게 되었다

 

 

UserDetailsService 커스텀 구현

 

우리가 커스텀해서 구현하는 거니까 UserDetailsService 인터페이스를 구현해주면 됨

스프링 부트한테 서비스단으로 등록되어야하니까 상단에 @Service 어노테이션 선언함

처음에 implements 했을때 오류 뜨는 이유는 @Override 해서 메서드를 구현시키지 않은 상태라서 그런거임

 

데이터베이스에 접근할 repository를 연결하기 위해서 repository 객체인 UserRepository 객체변수를 선언함 

UserEntity의 데이터를 가져와서 userRepository의 fidnByUsername 메서드에다가 여기서 인자로 받은 username 던져줌

조회한 데이터를 이제 검증하기 위해서 if(userData가 null이 아니면 return으로 CustomUserDetails를 만들어서 userData를 던져주면 됨 

그러면 여기서 CustomUserDetails가 없다고 뜨는데, 이유는 UserDetails라는 걸 만들어서 UserDetailsService에서 

최종적으로 manager한테 넘겨줄건데 그럼 이제 구현해야 한다

 

UserDetails 커스텀 구현

 

데이터를 넘겨주는 dto에 해당하기 때문에 dto 패키지에 구현한다

implements를 통해 UserDetails 인터페이스를 구현해준다

이렇게 작성하고 이제 CustomUserDetailsService에서 받아주면 오류 안 뜬다

null 값을 반환하는 getAuthorities 메서드의 경우 collection으로 ArrayList를 만들고 이에 데이터를 넣어줄건데

GrantedAuthority()를 넣어준다. GrantedAuthority 내부도 구현해야 하는데, 방법은 userEntity 객체에서 Role값만

뽑아서 응답해주면 된다. 외부 부분은 collection을 그대로 리턴해주면 된다

password의 경우 userEntity에서 getPassword를 통해서 리턴해줌

 

이제 뒷부분이 다 구현되었으니 실행하면 로그인이 진행될 것이다

그러면 필터에서 successfulAuthentication이 실행될 것이고 이제 간단하게 sout으로 글자를 찍어보겠다

 

회원가입 로직을 작성할때 유저네임:admin 패스워드:123 이라는 정보를 넣어두었고 그걸 로그인 하기위해서

postman에서 login 경로에다가 body 내부에 username에는 admin password에는 1234 라는 form-data를 넣어서 전송

 

이렇게 전송하면 로그인이 성공한 것을 확인할 수 있다 -> 응답 200 OK, sout success 찍힘

 

9. JWT 발급 및 검증 클래스

로그인이 성공하면 성공한 것에 대해서 사용자한테 JWT를 발급해줘야 됨

사용자는 JWT를 가지고 모든 경로에 대해서 접근을 함

접근할 때 해당 JWT가 우리 서버에서 생성되었는지, 유효기간이 지났는지 검증하는 검증 로직도 필요함

이에 대해서 발급과 검증을 담당할 클래스를 만들 것이다. 이를 JWTUtil 클래스라고 만들 것이다

 

JWT 생성 원리

JWT는 JSON 타입의 웹 토큰으로, 문자열 형태를 띄고 있음 중간에 .이 두 개 있는데 이를 통해서 

Header 부분, Payload 부분, Signature 부분을 나눠서 내부에 데이터를 전달하게 된다

 

Header는 이 토큰이 JWT임을 명시해주고, 사용한 암호화 알고리즘도 명시해준다

Payload는 실제로 사용자가 집어넣은 정보(username,role ...) 를 들고 있다

Signature는 이 토큰을 확인하고 검증할 수 있도록 BASE64 방식으로

헤더와 페이로드를 인코딩해서 최종적으로 시큐리티를 활용해서 암호화를 진행한다

 

JWT는 헤더와 페이로드는 간단하게 BASE64 방식으로 인코딩하기 때문에 외부에서 쉽게 디코딩해서

확인할 수 있다. 그렇기에 밖에서 열람해도 괜찮은 정보들만 넣어놔야 된다. 비밀번호값은 절대 담으면 안된다

토큰 자체의 발급처를 확인하기 위해서 사용하는 것이다

 

JWT 암호화 방식

JWT 암호화 방식에는 크게 양방향과 단방향이 있다

양방향은 암호화를 진행하면 다시 복호화할 수 있는 방식으로, 내부에 대칭키와 비대칭키 방식으로

양방향 암호화를 진행한다

대칭키는 동일한 키로 암호화와 복호화를 진행하고, 비대칭키는 public key와 secret(private?) key 둘 다 다른 키로 진행함

여기서는 양방향 대칭키 방식으로 진행할 것임 암호화 알고리즘은 HS256으로 진행

 

암호화 키 저장

JWT를 암호화 복호화 시킬 비밀번호를 만들어 놔야한다

비밀번호는 특정 자바 클래스에 넣는게 아니라 application.properties에 넣어놓을 것이다

이유는 하드코딩 방식으로 구현 내부에 탑재하면 외부에서 유출될 수도 있고 서버 여러개 띄울 때 암호 수정하기에 어려움

여기서 spring.jwt.secret은 임의로 지정한 이름이다 마음대로 설정하면 된다

 

영상에서 나온 키랑 동일하게 진행해볼 것이다 그냥 긴 문자열을 넣어주면 된다

이제 이 암호를 가지고 JWT를 만들 JWTUtil 클래스를 만들어보겠다.

 

JWTUtil

내부에 JWT를 검증할 메서드와 생성할 메서드를 생성할 것이다

 

토큰 Payload에 저장될 정보

- username

- role

- 생성일

- 만료일

 

JWTUtil 구현 메서드

- JWTUtil 생성자

- username 확인 메서드

- role 확인 메서드

- 만료일 확인 메서드

 

 

 

@Component의 경우는 스프링 부트한테 컴포넌트로 등록해서 관리되도록 붙여준다

JWT를 구현하는 방법은 버전에 따라 다른데 여기서는 최신의 버전으로 할 것이다

버전에 따라서 구현 방법이 좀 많이 다르다

 

구현하기 전에 생성자 방식으로 클래스가 호출이 되도록 내부에 저장해둔 시크릿키를 불러오도록 할 것임

Value 어노테이션으로 application.properties에 저장되어있는 특정 변수 데이터를 들고올 수 있음

이 데이터는 String secret 변수로 받아볼 것이다~

이 키는 특정하게 JWT에서 객체 타입으로 만들어서 저장해놔야됨 그래서 맨 상단에 객체키를 저장할

private SecretKey 객체를 생성할 것이다. 여기서 String 타입으로 받은 시크릿키를 객체 변수로 암호화하기 위한

메서드를 구현해놓은 것임- 

생성자에서 application.properties에 있는 키를 불러와서 그 키를 기반으로 어떠한 객체 키를 만들었음 

이제 내부에 메서드를 만들건데 위에서부터 세개 getUsername(), getRole(), isExpired() 검증을 위한 메서드고

마지막 createJwt()는 토큰을 생성하는 메서드이다

 

검증 메서드들의 경우, 토큰을 전달받아서 내부에 Jwts.parser()을 통해서 내부 데이터를 확인한다

토큰이 암호화가 진행되어있으므로 verifyWith()를 통해서 우리가 가지고 있는 secretKey를 넣어

토큰이 우리 서버에서 생성되었는지, 우리가 가지고 있는 것과 같은지 검증을 진행하고

builder 형식으로 리턴해주고, claim을 확인하고, payload에서 특정 데이터를 가져올 것임

특정한 데이터의 경우 .get을 통해서 획득할 수 있다 여기서는 username이라는 키를 가지고 있고

데이터 형식은 string으로 지정해주었다

 

isExpired()의 경우, Boolean 값으로 소멸되었으면 true 아니면 false로 리턴해준다

여기서는 getExpiration().before을 통해서 확인한다

 

createJwt()의 경우 로그인이 성공했을 때 사용 서버 successfulhandler를 통해서 username, role, 만료시간을

전달받아서 토큰을 생성해서 응답해주는 토큰 생성 메서드이다

토큰이 String이므로 리턴타입이 String이다 호출될 때 username, role, 만료시간을 인자로 받고

내부 메서드에서 jwts.builder()를 통해서 토큰을 만든다

내부에 claim이라고 선언한뒤에 특정한 키에 대한 데이터를 넣어줄 수 있다

토큰이 언제 발행되었는지 .issuedAt을 통해서 발행시간을 넣어줄 수 있다 

토큰이 언제 소멸될 것인지도 가능

최종적으로 .signWith(secretKey)를 통해서 암호화를 진행하고 compact()로 토큰을 컴팩시켜서 리턴해준다

 

10. 로그인 성공 JWT 발급

JWTUtil 클래스를 로그인 필터에서 주입받아가지고 로그인이 성공했을 때 실행되는 메서드에서

JWT를 발급해가지고 응답시켜주면 된다 그래서 이제 주입을 받을건데

LoginFilter에서 하단의 코드를 추가해준다

 

SecurityConfig에서 인자를 하나만 받았었기 때문에 오류가 발생한다 그러므로

SecurityConfig에서도 private final JWTUtil jwtUtil로 생성자 주입시켜주고

 

필터의 인자에다가 jwtUtil을 넣어주면 오류가 해결된다

 

그럼 이제 주입받은 JWTUtil을 통해서 로그인이 성공했을때 jwt 토큰을 만들어보도록 하겠다

 

LoginFilter 로그인 성공 successfulAuthentication 메서드 구현

 

JWT를 만들어서 Response에 넣어주도록 하겠다 기존에는 간단하게 systemout으로 "success" 이렇게 해줬었는데

그건 삭제하고, 우선 유저 객체를 알아내기 위해서 CustomUserDetails를 만들고 getPrincipal로 특정 유저를 확인한다

이렇게 하면 오류가 발생하는데, 타입 캐스팅 (CustomUserDetails)로 타입을 변경해준다

그리고 username을 customDetails에서 username을 뽑아낸다

role 값을 뽑아내기 위해서는, collection에서 authority 객체를 뽑아오고 iterator로 반복을 시켜서 내부 객체를 뽑아낸다

이렇게 authentication 객체로부터 뽑아낸 username과 role값을 jwtUtil에다가 토큰을 만들어달라고 전달할 것이다

그래서 jwtUtil에서 cretaeJwt라는 생성 메서드를 실행시키고 거기다가 username,role.jwt가 살아있을 시각을 인자로 넣음

response header에다가 담는데, 인증 방식을 접두사로 붙이고 띄어쓰기를 무조건 한번 해줘야된다 -> "Bearer " 

 

이러한 인증 방식을 사용하는 이유는 http 인증 방식 중에 RFC 7235 정의에 따라서 헤더 부분에 Authorization 인증 방식을

집어넣을 때 앞에 접두사를 꼭 붙이는 것을 공식적으로 정의하고 있기 때문이다

 

LoginFilter 로그인 실패 unsuccessfulAuthentication 메서드 구현 

실패했을때는 간단하게 response 값으로 401 응답코드를 보낼 것이다

 

JWT 발급 테스트

미리 회원가입을 통해서 admin과 1234라는 아이디와 비밀번호를 넣어두었고, 이를 통해 로그인을 진행하면

 

응답 코드가 200이 뜨면서, 응답 헤더에 Authorization이라는 키 값에 대한 JWT값을 확인할 수 있다

앞으로 이 값을 복사해서 어떠한 요청을 보낼 때 헤더값에 넣어서 보내줄 것이다

지금까지 로그인 구현하고 JWT가 로그인이 완료되었을때 발급되는것까지 만들었다

토큰이 응답 헤더에 담기고 그 토큰을 그대로 복사해가지고 특정 다른 경로에 요청을 진행할 때 요청 헤더에다가

Authorization 키에다가 토큰을 넘겨서 전송하면 됨

11. JWT 검증 필터

아직은 /admin 경로에 대해 토큰을 가지고 접근하면 접근이 거부된다 이유는 토큰을 검증해주는 필터를 등록하지 않아서

토큰에 대한 검증을 진행할 수 없기 때문이다

이 방법도 잠깐의 세션의 방법을 이용하긴함 그치만 그 세션이 STATELESS 상태로 관리되기 때문에 한번의 요청만

기억하고 다시 동일한 요청을 보내면 다시 토큰을 보내서 세션이 잠깐 생성이 되고 없어지기 때문에 세션이 STATELESS 상태로 관리됨

 

+ 여기서 STATELESS (무상태성) 이란 서버가 클라이언트의 상태를 보존하지 않음을 의미한다

오직 클라이언트의 요청에 대한 응답만 주는데, HTTP 통신이 이를 지향한다. 왜냐면 요청(트래픽)이 갑자기

증가할 때 서버를 추가하기가 쉬워짐

 

그러면 이제 JWT를 검증할 커스텀 필터를 만들어야 된다 그리고 구현한 필터를 등록만 시켜주면

JWT 기능적인 부분은 구현이 완료된다~

 

JWTFilter 구현

 

커스텀 필터를 만들기 위해서, 요청에 대해서 한번만 동작하는 OncePerRequestFilter 필터를 상속받아서 만들 것이다

이렇게 상속시켜주면 처음에는 어떠한 메서드를 구현하라고 오류가 발생하는데, override해서 해주면 됨

protected 접근제어자를 가지고 있는 doFilterInternal이라는 메서드를 구현해주면 됨

메서드 내부에는 필터에 대한 특정 구현을 진행할 거고 JWT를 request에서 뽑아내서 검증을 진행할건데

그러려면 JWTUtil에서 필터를 검증할 메서드를 가지고 와야한다 -> 그래서 주입받기 위해서 private final  JWTUtil 선언

생성자 방식으로 Util을 주입받으면 된다 -> 그냥 @AllArgsConstructor 씀 

 

이제 내부에 토큰을 검증하는 여러가지 메서드를 구현해보겠다

request에서 헤더값을 뽑아올건데 키 값이 Authorization인 헤더를 뽑아오고 그걸 String에 담을 거다

이제 그 뽑아온 키 값에서 Authorization 변수에 토큰이 담겼는지 그게 null인지 아니면 인증 방식 접두사 Bearer를 가지지 않았는지 확인하기 위해서 if문으로 조건을 달았다. ( || 논리연산자 OR은 둘중 하나라도 참이면 됨)

-> 이렇게 authorization값이 null이거나 접두사가 Bearer로 시작하지않는 토큰이면 이 메서드를 종료시킴

return하기 전에 doFilter를 통해 여러 체인 방식으로 엮여있는 필터들을 종료하고 그 필터에서 받은 request와 response를

다음 필터로 넘겨준다

 

위에서는 토큰이 null값인지 아닌지 검증을 하였고, 그 다음은 토큰을 분리해서 토큰에 대해서 소멸시간을 검증할 것임

그래서 이제 앞에 접두사인 Bearer를 제거할 것이므로 split을 통해서 띄어쓰기 구문으로부터 앞부분과 뒷부분 인덱스를

가지는 리스트가 생성된다 그 리스트 중에 두번째인 (1번 인덱스)를 토큰으로 받으면 된다

if문을 통해서 토큰이 존재하는데 소멸시간이 지났는지 검증을 진행해보도록 하겠다

이는 jwtUtil 클래스에 isExpired를 구현했었다 

 

 

그래서 위 두 과정을 거치고 나면 null 값도 아니고, 소멸시간도 지나지 않았기 때문에 최종적으로 토큰을 확인할 수 있게됨

그러면 그 토큰을 기반으로 일시적인 세션을 한 개 만들어서 SecurityContextHolder라는 시큐리티 세션에다가 우리의

user를 일시적으로 저장시켜주면 특정한 admin 경로나 유저 정보를 요구하는 경로의 요청을 진행할 수 있게됨

저장하는 방법은 token에서 username이랑 role값을 jwtUtil의 메서드를 통해서 일단 꺼내온다

userEntity 클래스에다가 값들을 초기화시켜주고, 중요한 점은 비밀번호는 담기지 않았지만 초기화 진행해줘야되는데

비밀번호는 db에서 조회를 하면 매번 요청할때마다 DB에서 조회하는 안 좋은 상황이 발생하기 때문에 

ContextHolder에다가 정확한 비밀번호를 넣어줄 필요가 없다 그래서 임시적으로 비밀번호를 하나 만들어가지고

초기화 시켜준다

userEntity에 유저 객체를 하나 만들어가지고 CustomUserDetails에다가 유저 객체를 넣어가지고 하나 만들도록 하고,

만든 UserDetails 객체를 UsernamePasswordAuthenticationToken을 만들어서 토큰을 생성하도록 할 것이다

그래서 최종적으로 SecurityContextHolder에다가 넣어주면 지금 요청에 대해서 유저 세션을 생성할 수 있음

이제 세션이 생성되었기 때문에 특정 경로에 접근할 수 있고 마지막으로, 메서드가 종료되었기 때문에 

filterChain을 통해서 그 다음 필터에게 우리의 필터가 받았던 request와 response를 넘겨주면 된다

 

SecurityConfig JWTFilter 등록

 

 

SecurityConfig에 등록해서 시큐리티가 동작할 때 이 필터도 동작할 수 있도록 등록만 진행하면 된다

SecurityConfig에 필터를 추가하는 방법은 특정 필터 앞에다가 추가하는 .addFilterBefore를 통해서 하면 된다

new를 통해서 JWTFilter를 넣어주고, 필터의 위치는 loginFilter 앞에다가 둔다

JWTFilter의 경우 JWTUtil을 주입받았으므로 이 클래스에서도 JWTUtil을 주입받는다 (저번 시간에 미리 해놓음)

 

그니까 기존 SecurityConfig 코드에 위 코드만 추가하면 등록 끝이다

 

JWT 요청 인가 테스트

 

이렇게 로그인을 진행한 뒤 응답 헤더의 토큰을 일단 복사하고


Bearer eyJhbGciOiJub25lIn0.eyJ1c2VybmFtZSI6ImFkbWluIiwicm9sZSI6IlJPTEVfQURNSU4iLCJpYXQiOjE3MjY2NDA5NTYsImV4cCI6MTcyNjY0MDk5Mn0. 

 

!!! 여기서 JWT가 잘못 생성되고 있는 오류 발생함 .... 서명 알고리즘 HS256을 사용한 JWT는 세 부분으로 나뉘는데현재 생성된 값은 세번째 부분인 서명이 포함이 안되어있음

이유는 별게 아니었다 ....... JWTUtil을 작성할 때 createJwt 메서드에서 .signWith(secretKey) 코드를실수로 빼먹어서 ............

 

이렇게 JWTUtil에 추가해주었다

이제 POSTMAN에서 다시 login 요청을 해서 생성되는 JWT를 다시 확인해보면,

 

 

이번에는 제대로 생성된 것을 확인해볼 수 있다 ->

 

Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwicm9sZSI6IlJPTEVfQURNSU4iLCJpYXQiOjE3MjY2NDYxMDksImV4cCI6MTcyNjY0NjE0NX0.uNYUOCLiV5mLr69JGq6ljpG6skAW54kj3qlW3S1gauA

 
근데 이번에는 정상적인 토큰 값을 보내줬는데도 .이 없다는 오류를 발생시킨다...
 

 

또 코드를 빼먹고 작성하는 실수도 있었다  SecurityConfig 클래스에서

 

requestMatchers /admin을 빼먹었다.... ;  그러나 이를 수정해줬는데도 오류는 해결되지 않았음

강의 코드 다운받아서 돌려봤는데 똑같은 오류가 발생함

코드 문제가 아닌 것 같다 나중에 리눅스 환경에서도 그대로 시도해보고 해결해보겠음...

https://substantial-park-a17.notion.site/1-11-8f1a0ab664fb4d888b279d2fcd7b0afa

 

1~11강 코드 파일 | Notion

최종 변경 : 2023.12.30

substantial-park-a17.notion.site

 

12. 세션 정보

추가적으로 로그인한 사용자에 대해서 해당 컨트롤러에서 해당 ID를 뽑거나 ROLE값을 뽑는 세션 확인에 대해서 알아볼 것이다 

JWT 자체가 세션을 STATELESS하게 관리하긴 하지만, JWT를 가지고 JWT 필터를 통과한 순간 일시적으로 세션을

만들기 때문에 SecurityContextHolder에서 세션에 대한 사용자 이름을 확인할 수 있음

 

JWTFilter를 통과한 뒤 세션 확인 

 

메인페이지에 구현해보도록 할 것임

SecurityContextHolder.부터 getName() 이거는 세션 현재 사용자 아이디를 받아오는 구문이다

 

role의 경우, 컬렉션을 iterator 형식으로 돌아서 그 내부에 role값을 빼내야한다

그래서 role 코드를 추가하면 아래 코드로 된다

 

 

그러면 위에서 한 것처럼 /login 경로로 admin으로 로그인해서 응답 헤더에서 JWT 뽑아서, / 메인 경로로 헤더에

JWT를 넣어서 GET 요청 보내면, 아래처럼 뜰 것이다

 

 

JWT는 STATELESS 상태로 관리되긴 하지만, JWT를 통해서 일시적인 요청에 대해서는 세션을 잠시동안 생성하므로

내부 SecurityContextHolder에 대해서 사용자 정보를 꺼낼 수 있음

 

13. CORS 설정

CORS란 Cross-Origin Resource Sharing이라고 서로 다른 도메인간의 자원 요청을 허용하거나 차단하는 메커니즘을

말함. 웹 브라우저는 보통 동일 출처 정책이라고 하는 보안 정책에 따라 기본적으로 다른 도메인 간의 요청을 차단함

그런데 특정 경우는 다른 출처에서 자원을 요청해야 할 필요가 있는데, 이를 가능하게 하는게 CORS.

한마디로 CORS는 허가되지 않은 외부 요청을 막고, 악의적으로 정보가 탈취되는 것을 막는다

 

발생 원리

 

클라이언트가 웹 브라우저를 통해서 사이트에 접속하게 되면 프론트에서 리액트를 응답해준다

프론트는 보통 localhost:3000로 띄어서 테스트를 하게 되고 응답받은 페이지에서 특정 내부 데이터를

api 서버로 호출하게 되면 api 데이터는 8080 포트에서 응답이 되게 됨

이렇게 되면 두 개의 서버 포트번호가 다르므로 웹 브라우저단에서 교차 출처 리소스 공유를 금지시키므로

데이터가 보이지 않게 됨 우리가 백엔드에서 무조건 CORS 설정 처리를 해줘야지 앞단에서 데이터가 보이므로 처리를

꼭 해줘야함.

 

그 방법에는 시큐리티 쪽에서 설정하는 방법과 서블릿방식인 MVC Config에서 설정하는 두 가지 방법을 처리해줘야함

컨트롤러단으로 들어오는 애들은 MVC에서 처리해줘야하고 나머지 시큐리티 필터를 타는 애들은 시큐리티 쪽에서

처리해줘야하므로 두 가지 방법 모두 설정해줘야 함

 

내부 시큐리티 필터 체인을 리턴하는 메서드에다가 구현하도록 할 것임

 

CORS 설정: SecurityConfig 클래스

 

람다식으로 cors 변수를 받을건데 configurationSource 메서드를 가지고 올거고, 내부에 생성자를 통해서 

CorsConfigurationSource를 바로 만들면 됨 밑에다가 따로 분리해도 되지만 바로 만들 것이다

override해서 내부 구현하면 됨

내부에다가 CorsConfiguration 클래스를 가지고 와서 new를 통해서 만들고 내부에다가 각각 configuration에다가 

특정 값들을 세팅해주면 된다

총 여섯개의 변수가 있는데, 

1. 허용할 앞단의 프론트 서버에서 보낼 것이므로 3000번대 포트를 허용한다

2. 허용할 메서드의 경우는 모든 요청을 허용해줌

3. 프론트에서 Credentials 설정을 하면 여기서도 무조건 true로 바꿔줘야함

4. 허용할 헤더의 경우는 모든 헤더를 허용해줌

5. 허용할 시간

6. 프론트로 헤더를 보내줄 때 Authorization의 JWT를 보내줄 것이므로 Authorization 헤더도 허용시켜줘야함

최종적으로 return은 위에서 만든 configuration을 리턴해주면 됨

 

이렇게 되면 시큐리티 쪽 설정은 끝났음 이렇게 되면 로그인 필터 쪽 애들이 CORS 설정에 벗어나게 되고

나머지 컨트롤러단 문제도 해결해줄 것이다

 

CORS 설정: config> CorsMvcConfig 클래스

 

컨트롤러단 문제 해결을 위해서 config 패키지에서 CorsMvcConfig 클래스를 만들어준다

configuration 클래스로 등록되기 위해서 @Configuration 어노테이션을 써준다

WebMvcConfigurer를 구현해줄 것이고 addCorsMappings 메서드만 구현시켜주면 됨

모든 컨트롤러 경로에 대해서 3000 요청이 오는 주소를 넣어주면 됨

 

14. JWT의 목표

a