spring boot // JWT 만들기
아래 프로젝트를 참고하여 진행 (내용이 약간다름)
https://github.com/codingspecialist/Springboot-Security-JWT
위 프로젝트 연구
https://ondolroom.tistory.com/690
사전 정보
https://ondolroom.tistory.com/687
현재 프로젝트 (아래 코드 설명을 참고하려면 이곳을 확인)
https://github.com/jaybon1/springwork/tree/master/jwtEx01
프로젝트 명 생성
필요한 의존성 추가
---------
프로젝트 구조
----------
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번 방식을 개선한 방식
----
마지막으로 필터체인으로 다시 돌아간다