Server/Spring Boot

spring boot // JWT 만들기

Jaybon 2020. 8. 7. 17:53

 

아래 프로젝트를 참고하여 진행 (내용이 약간다름)

https://github.com/codingspecialist/Springboot-Security-JWT

 

codingspecialist/Springboot-Security-JWT

Contribute to codingspecialist/Springboot-Security-JWT development by creating an account on GitHub.

github.com

 

위 프로젝트 연구

https://ondolroom.tistory.com/690

 

spring boot // Springboot-Security-JWT 프로젝트 분석

연구할 프로젝트 https://github.com/codingspecialist/Springboot-Security-JWT codingspecialist/Springboot-Security-JWT Contribute to codingspecialist/Springboot-Security-JWT development by creating an..

ondolroom.tistory.com

 

사전 정보

https://ondolroom.tistory.com/687

 

spring boot // 토큰 기반 / JWT 정보

아래 사이트를 참고하여 정리합니다 https://velopert.com/2350 [JWT] 토큰(Token) 기반 인증에 대한 소개 | VELOPERT.LOG 소개 토큰(Token) 기반 인증은 모던 웹서비스에서 정말 많이 사용되고 있습니다. 여러분.

ondolroom.tistory.com

 

현재 프로젝트 (아래 코드 설명을 참고하려면 이곳을 확인)

https://github.com/jaybon1/springwork/tree/master/jwtEx01

 

jaybon1/springwork

Contribute to jaybon1/springwork development by creating an account on GitHub.

github.com

 

프로젝트 명 생성

 

 

필요한 의존성 추가

---------

 

프로젝트 구조

----------

 

 

pom.xml

JWT 의존성 추가

		<dependency>
			<groupId>com.auth0</groupId>
			<artifactId>java-jwt</artifactId>
			<version>3.4.1</version>
		</dependency>

--------

 

application.yml

----

 

RestApiController.java

@RequestMapping("api/v1") // 공통 진입경로 확인

@Autowired 를 사용하지 않고 DI할 것들에 final 붙이고 @RequiredArgsConstructor를 붙여주면 똑같은 효과

---------

 

 

SecurityConfig.java

메서드를 IOC 하기 위한 @Bean

 

1. STATELESS로 만들면 jsessoinId를 만들지 않는다

2. /login 경로로 접근시 해당필터에 걸리게 된다

3. 해당 경로로 접근시 ROLE이 맞는 사람만 접속 하도록 한다

.anyRequest().permitAll() 나머지 요청은 모두 허용한다

-----------

 

CorsConfig.java

cors()옵션 - 기타도메인의 자바스크립트 요청을 거부

@CrossOrigin은 컨트롤러 클래스가 아닌 메서드에 거는 것을 추천

전역적으로 설정하려면 아래와 같이 파일 생성하여 입력

 

 

User.java

원래 model에는 setter를 달면 안된다 - DTO를 이용하자

--

 

LoginRequestDto.java

로그인 데이터를 전송하기위한 DTO

 

 

PrincipalDetails.java

UserDetails를 상속하기 위한 클래스

User 객체를 컴포지션 한다

()-> 화살표 함수를 사용하면 GrantedAuthority와 관련된 클래스를 지정하지 않고도 자동으로 만들 수 있다

---------

 

 

PrincipalDetailsService.java

DB에서 유저를 검색하여 있으면 UserDetails를 리턴한다

-------

 

 

JwtAuthenticationFilter.java

------

 

1. attemptAuthentication은 인증 요청시에 실행 된다 (/login)

2. ObjectMapper는 데이터가 어떠한 형식으로 들어오더라도 값을 변환하여 객체에 담아준다

3. attemptAuthentication을 커스텀하면 UsernamePasswordAuthenticationToken을 직접 만들어 줘야한다

4. 아래 주석 참고

--------

 

1. Authentication 객체에서 PrincipalDetails를 가져온다

2. 클레임들을 삽입하고 암호알고리즘을 추가하여 JWT토큰을 만든다

3. 만들어진 토큰을 헤더에 넣는다

-------

 

 

JwtAuthorizationFilter.java

BasicAuthenticationFilter는 헤더전문 필터

--

 

팁 : 내가 new 한 클래스는 Autowired가 안된다

매개변수로 userRepository를 받아서 전역변수에 담아준다

----

 

1. 인증필터가 끝나면 인가필터로 넘어오는 것

2. 헤더값에 JWT토큰이 있는지 확인하여 없으면 돌려보낸다

3. 토큰이 있다면 JWT토큰에서 베리어와 패딩을 뺀 순수한 토큰값을 가져온다

---

 

토큰 검증하기
시크릿 키값과 함께 암호화된 파일을 풀어서 유저네임을 가져온다
암호화를 풀고 유저네임을 가져온 것 자체가 검증이 끝났다는 것

---

 

인가 1번방식

1. 위에서 검증이 끝난 유저네임으로 리파지토리에서 데이터를 받아
UserDetails 를 상속받은 PrincipalDetails를 만든다

2. UsernamePasswordAuthenticationToken을 만들고
authenticationManager를 사용하지 않고 usernamePasswordAuthenticationToken를 이용하여 Authentication 제작

3. 시큐리티 세션저장공간에 authentication을 넣는다.

----

 

인가 2번 방식

1. 위에서 검증이 끝난 유저네임으로 리파지토리에서 데이터를 받아 sessionUser라는 DTO에 넣어준다

2. 시큐리티세션(authentication)이 아닌 일반세션에 넣어준다

----

 

컨트롤러에서 일반세션 테스트용 메서드를 매핑한다

--

 

콘솔창 확인

--

 

포스트맨 확인

--

 

인가 3번 방식


클레임에 ROLE을 넣어서 바로어썬티케이션 만들기
(이렇게 만들면 리파지토리에서 유저를 가져올 필요도 없다 / 토큰에서 인증한 데이터로 만들면되기 때문)

--

 

인가 4번 방식

1번 방식을 개선한 방식

----

 

마지막으로 필터체인으로 다시 돌아간다