Spring Boot JWT Tutorial (1)설정, DB
===
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-jwt/dashboard
[무료] Spring Boot JWT Tutorial - 인프런 | 강의
Spring Boot, Spring Security, JWT를 이용한 튜토리얼을 통해 인증과 인가에 대한 기초 지식을 쉽고 빠르게 학습할 수 있습니다., - 강의 소개 | 인프런...
www.inflearn.com
Q.
52초쯤 JWT를 적용함에 있어서 몇가지 고려해야할
사항들을 잘 대응하면 대규모 프로젝트에서도 적용할 수 있다고 하셨는데요!
고려해야될 사항을 좀 더 추가로 설명을 해주시면
감사하겠습니다!
A.
고려해야될 사항이라는 것은 해당 시스템의 요구사항에 따라 수많은 사항들이 생길 것 같다고 생각합니다.
가장 간단한 예를 든다면
가령 "시스템은 사용자에게 발급된 토큰 중 특정 토큰을 지정하여 사용을 중지시킬 수 있다" 라는 요구사항이 있다고 한다면
토큰의 만료시간만 가지고 해당 요구사항을 충족시킬 수는 없겠죠. 그때는 서버사이드에서 해당 요구사항을 충족하기 위한 추가 개발들을 해야할 것 이라고 생각이 듭니다.
이 요구사항을 충족하기 위해 몇가지 생각해보면 아래와 같은 방법들이 있을 것 같습니다.
- 권한 DB의 Version 정보를 관리해서 권한이 수정되면 Version을 변경하고 JWT 내의 Version 정보와 비교해서 틀리면 Update
- JWT 만료 날짜를 짧게 유지한다.
- 토큰을 Redis 혹은 DB 같은곳에 저장해놓고 권한이 변경되면 해당 토큰을 업데이트 대상 토큰으로 저장하여 놓고 권한이 필요한 API를 요청할 시 업데이트 대상 토큰을 검증하는 필터를 구현하여 업데이트
- JWT 페이로드에 발급 시간을 저장해 놓고 권한이 변경된 시간과 비교 업데이트
일단은 JWT의 기초 지식에 대해 먼저 습득하신 후에 실제 본인만의 서비스를 만들어서 적용해보시길 추천드립니다. :)
===
JWT :
RFC 7519 웹표준 JSON
객체를 사용해서 토큰 자체에 정보들을 저장하고 있는 Web Token
간편하고 쉽게 적용 가능
===
Header : Signature를 해싱하기 위한 알고리즘 정보를 담는다
Payload : 서버와 클라이언트가 주고받는, 시스템에서 실제로 사용될 정보에 대한 내용들을 담는다
Signature : 토큰의 유효성 검증을 위한 문자열, 서버가 체크함
===
===
[실습]
Spring Web, Spring Security, Spring Data JPA, H2, Lombok, Validation
IntelliJ를 쓰면 Lombok을 쓸 때 저걸 체크해야
===
이 상태인데
▽실행을 하려니까
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-validation'
//implementation 'org.springframework.boot:spring-boot-starter-web'
runtimeOnly 'com.h2database:h2'
//testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
얘네를 추가하고 h2안쓸것같지?하면서 주석처리 하고
실행했더니
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
아하?주석뺐더니
Unauthorized가 뜬다.
(▽원래는 그냥 떠야하잖아. security다시 빼면 나온다. 요즘은 패치돼서 Body에 아무것도 안나오는듯 똑같이 프로젝트 따라해봤는데 안나옴)
이를 해결하기 위한 Security설정과 기본적인 Data 설정들을 진행해야한다
====================================
====================================
이제부터 할 것
기본적인 Security 설정을 위해 SecurityConfig 클래스를 만든다.
기본적인 Web 보안을 활성화 하겠다는 애너테이션
추가적인 설정을 위해 WebSecurityConfigurer를 implements하거나
WebSecurityConfigurerAdapter를 extends하는 방법이 있다
여기선 후자택
===
WebSecurityConfigurerAdapter의 configure메소드를 오버라이드
authorizeRequests : HttpServletRequest를 사용하는 요청들에 대한 접근제한을 설정하겠다
anyMatchers("/api/hello").permitAll() : /api/hello에 대한 요청은 인증없이 접근을 허용하겠다는 의미
anyRequest().authenticated() : 나머지 요청들은 모두 인증돼야 한다는 의미
그럼이제
잘됨
===
DataStore에 대한 설정
application.properties파일을 Refactor를 이용해서 application.yml로 파일명을 변경하겠습니다
(그냥 더 보기 편해서 변경한 것)
h2 DB사용, 메모리에 데이터 저장 할것
h2 console을 enable했고
Datasource 설정 추가
JPA설정 추가, create-drop은 SessionFactory가 시작될 때 Drop, Create, Alter 를 하고 / 종료될 때 Drop 진행
콘솔창에서 실행되는 sql들을 보기좋게 보여주는 설정추가
로깅레벨 디버그
===
create-drop은 SpringBoot 서버가 시작될 때마다 테이블들을 새로 만든다 -> 편의를 위해 초기 Data를 자동으로 DB에 넣어주는 기능을 활용하겠다
resource > data.sql
에다 넣으면 이 쿼리들이 실행이 된대 왜??
===
entity 패키지 생성, User, Authority 클래스 생성
@Entity
@Table(name = "user")
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class User {
@Id
@Column(name = "user_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long userId;
@Column(name = "username", length = 50, unique = true)
private String username;
@Column(name = "password", length = 100)
private String password;
@Column(name = "nickname", length = 50)
private String nickname;
@Column(name = "activated")
private boolean activated;
@ManyToMany
@JoinTable(
name = "user_authority",
joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "user_id")},
inverseJoinColumns = {@JoinColumn(name = "authority_name", referencedColumnName = "authority_name")})
private Set<Authority> authorities;
}
User의 애너테이션 설명 :
@Entity : 데이터베이스의 테이블과 1:1 매핑되는 객체를 뜻함
@Table : name으로 테이블 명 이름 지정 위해 씀
User의 필드 설명 :
@ManyToMany, JoinTable은 User객체와 권한객체의 다대다 관계를 일대다, 다대일 관계의 조인 테이블로 정의했다는 뜻
@Entity
@Table(name = "authority")
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Authority {
@Id
@Column(name = "authority_name", length = 50)
private String authorityName;
}
===
만들었던 엔티티들이 DB에 생성이 되는지 확인하기 위해 h2-console을 이용하려고 하는데
그 전에 Security 설정을 추가해줘야 h2-console접근을 원활하게 할 수 있다.
SecurityConfig로 가서 configure(WebSecurity web) 메소드 오버라이드
h2-console 하위 모든 요청들과 파비콘 관련 요청은 Spring Security 로직을 수행하지 않도록
서버를 실행하면
실제 DB확인하기, 브라우저 열고 localhost:8080/h2-console
잘 나옴