먼저 다음과 같이 프로젝트를 생성해준다.
// gradle
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'io.jsonwebtoken:jjwt-impl:0.11.5'
implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5'
build.gradle에 위 dependency를 추가하자.
application.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/jwt
username:
password:
jpa:
hibernate:
ddl-auto: update
properties:
hibernate:
show_sql: true
yml파일 설정은 위와 같이 했다.
Member Entity를 만들어보자.
Member
package com.jwt.domain.member;
import jakarta.persistence.*;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Entity
@Getter
@NoArgsConstructor
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "member_id")
private Long id;
@Column(unique = true, length = 50)
private String email;
@Column(length = 100)
private String password;
@Column(length = 50)
private String username;
@Enumerated(EnumType.STRING)
private Role role;
@Builder
public Member(String email, String password, String username, Role role) {
this.email = email;
this.password = password;
this.username = username;
this.role = role;
}
}
MemberRepository
package com.jwt.domain.member;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface MemberRepository extends JpaRepository<Member, Long> {
Optional<Member> findByEmail(String email);
boolean existsByEmail(String email);
}
Role
package com.jwt.domain.member;
public enum Role {
ROLE_USER,
ROLE_ANONYMOUS,
ROLE_ADMIN
}
Role은 3개만 써두자.
UserPrinciple
package com.jwt.domain.member;
import lombok.Getter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import java.util.Collection;
@Getter
public class UserPrinciple extends User {
private static final String PASSWORD_ERASED_VALUE = "[PASSWORD_ERASED]";
private final String email;
public UserPrinciple(String email, String username, Collection<? extends GrantedAuthority> authorities) {
super(username, PASSWORD_ERASED_VALUE, authorities);
this.email = email;
}
@Override
public String toString() {
return "UserPrinciple{" +
"email='" + email +
" username='" + getUsername() +
" roles=" + getAuthorities() +
'}';
}
}
UserDetail
인터페이스의 구현체 User
를 사용하되 필요한 email필드를 추가하기 위해 extends를 사용했다.
이 객체를
principal에 넣어줄 예정이다.
즉 우리의 SecurityContext의 principal에는 email
와 기본 User
에 포함되어 있는 필드인 username
, password
, Authorities
등의 정보가 들어갈 예정이다.
password
는 보안의 목적으로 객체 생성시에 지우도록 했다.