[Spring] Spring Security + JWT 로그인 구현 해보기 - 1 (설정, 도메인 생성, 레포 생성)

이혜지·2022년 3월 20일
0

Spring Security + JWT

목록 보기
2/5
post-thumbnail

나는 MySQL 말고 PostgreSQL 사용했다.

다운을 받고 build.gradle을 사용하여 project를 열고

dependency 몇가지를 추가해주자.

	//jwt
	implementation 'io.jsonwebtoken:jjwt-api:0.11.2'
	implementation 'io.jsonwebtoken:jjwt-impl:0.11.2'
	implementation 'io.jsonwebtoken:jjwt-jackson:0.11.2'
    
    //<!-- For Java 8 Date/Time Support -->
	// https://mvnrepository.com/artifact/com.fasterxml.jackson.datatype/jackson-datatype-jsr310
	implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'

서버, 데이터베이스, Hibernate, Jackson 설정

server:
  port: 8080
  servlet:
    context-path: /
    encoding:
      charset: utf-8
      enabled: true

spring:
  profiles:
    include: aws
  output.ansi.enabled: always
  jpa:
    open-in-view: false
    hibernate:
      ddl-auto: update # create, update, none
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
    #show-sql: true
    format-sql: true
    properties:
      hibernate:
        dialect: org.hibernate.dialect.PostgreSQLDialect
        default_schema: 스키마 이름
    defer-datasource-initialization: true

# DB설정은 본인 DB설정 찾아서 yml 파일에 해주면 된다.

  jackson:
    serialization:
      write-dates-as-timestamps: false
    time-zome: Asia/Seoul

app:
  jwtSecret: jwtsigntutorialasdfasdfasdfasdfasdf
  jwtExpirationInMs: 604800000

logging.level:
  org.hibernate.SQL: debug
  org.hibernate.type: trace

Jackson의 WRITE_DATES_AS_TIMESTAMPS속성은 Java 8 데이터/시간 값을 타임스탬프로 직렬화하는 것을 비활성화하는 데 사용됩니다. 모든 날짜/시간 값은 ISO 날짜/시간 문자열로 직렬화됩니다.

Java8 날짜/시간 설정을 위해 Spring Boot 구성

도메인 모델에서 Java 8 데이터/시간 클래스를 사용할 것입니다. JPA 2.1 변환기를 등록해야 도메인 모델의 모든 Java 8 날짜/시간 필드가 데이터베이스에 유지될 때 자동으로 SQL 유형으로 변환됩니다.


@EnableJpaAuditing
@SpringBootApplication
@EntityScan(basePackageClasses = {
	BackendApplication.class,
	Jsr310JpaConverters.class
})
public class BackendApplication {

	@PostConstruct
	void init() {
		TimeZone.setDefault(TimeZone.getTimeZone("Asia/Seoul"));
	}

	public static void main(String[] args) {
		SpringApplication.run(BackendApplication.class, args);
	}
}

도메인 모델 작성

모든 사용자는 하나 이상의 역할을 갖습니다. 사용자와 관련된 역할은 향후 사용자가 당사 서버의 특정 리소스에 액세스할 수 있는 권한이 있는지 여부를 결정하는 데 사용됩니다.

이 섹션에서는 User및 Role도메인 모델을 생성합니다. model이라는 패키지 생성하세요 ~

1. User 모델

User모델에는 다음 필드가 포함됩니다 .

  • id: 기본 키
  • username: 고유한 사용자 이름
  • email: 독특한 이메일
  • password: 암호화된 형식으로 저장될 비밀번호입니다.
  • roles: 역할 집합입니다. Role( 엔티티 와의 다대다 관계 ) -> 다대다는 안좋은데.,.암튼 다대다임

User.java


@Entity @Getter @Setter
@Table(name = "users")
public class User extends BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank
    @Size(max = 40)
    private String name;

    @NotBlank
    @Size(max = 15)
    private String username;

    @NaturalId
    @NotBlank
    @Size(max = 40)
    @Email
    private String email;

    @NotBlank
    @Size(max = 100)
    private String password;

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "user_roles",
            joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "role_id"))
    private Set<Role> roles = new HashSet<>();

    public User() {

    }

    public User(String name, String username, String email, String password) {
        this.name = name;
        this.username = username;
        this.email = email;
        this.password = password;
    }
}

참고로 @NotBlank, @Size 같은 제한사항은 도메인이 아니라 DTO에서 검증해주는게 좋다.

2. Role 모델
Role클래스에는 및 필드 id가 포함됩니다. 필드는 name입니다 . 미리 정의된 고정된 역할 집합이 있습니다. 따라서 역할 이름을 로 만드는 것이 좋습니다

Role.java


@Entity @Getter @Setter
@Table(name = "roles")
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Enumerated(EnumType.STRING)
    @NaturalId
    @Column(length = 60)
    private RoleName name;

    public Role() {

    }

    public Role(RoleName name) {
        this.name = name;
    }
}

RoleName enum 작성

public enum  RoleName {
    ROLE_USER,
    ROLE_ADMIN
}

3. BaseEntity 작성
audit이라는 패키지를 새로 생성해주시고 그안에 작성~

createdAt및 updatedAt필드 가 있을 것 입니다. 이러한 감사 필드가 필요한 다른 도메인 모델은 단순히 이 클래스를 확장합니다.

@EqualsAndHashCode
@MappedSuperclass
@Getter
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties(
	value = {"createdAt", "updatedAt"},
	allowGetters = true
)
public abstract class BaseEntity {

	@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
	protected Long id;

	@CreatedDate
	@Column(nullable = false)
	private LocalDateTime createdAt;

	@LastModifiedDate
	private LocalDateTime updatedAt;
}

User, Role 레포지토리 생성

JPA를 이용한 데베에 유지하고 검색하기 위한 레포 생성

repository라는 패키지 생성해주시고 그 안에 작성해주세요.

1. UserRepository.java

import com.example.polls.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;

public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByEmail(String email);

    Optional<User> findByUsernameOrEmail(String username, String email);

    List<User> findByIdIn(List<Long> userIds);

    Optional<User> findByUsername(String username);

    Boolean existsByUsername(String username);

    Boolean existsByEmail(String email);
}

2. RoleRepository.java

import com.example.polls.model.Role;
import com.example.polls.model.RoleName;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;

@Repository
public interface RoleRepository extends JpaRepository<Role, Long> {
    Optional<Role> findByName(RoleName roleName);
}

DB에 기본 역할 생성

애플리케이션에는 미리 정의된 고정된 역할 집합이 있습니다. 사용자가 로그인할 때마다 ROLE_USER기본적으로 할당됩니다.

역할을 할당하려면 데이터베이스에 있어야 합니다. 따라서 다음 삽입 문을 실행하여 데이터베이스에 두 개의 기본 역할을 생성해 보겠습니다.

INSERT INTO roles(name) VALUES('ROLE_USER');
INSERT INTO roles(name) VALUES('ROLE_ADMIN');

다음편에서는 Spring Security를 구성하고 새 사용자를 등록하고 로그인하는 기능을 추가하겟습니다

profile
공유 문화를 지향하는 개발자입니다.

0개의 댓글