개요
이번에는 JWT토큰을 기반으로 회원가입, 로그인을 구현해보기 위해서 환경세팅, 프로젝트 생성을 해보겠습니다.
- 회원가입
내부 회원가입 로직은 세션방식과 차이가 없습니다.
POST요청으로 받아서 내부적으로 요청받아서 서비스에서 처리하고 entity에서 저장합니다. - 로그인
로그인 요청을 받은 후 세션 방식은 서버 세션이 유저정보를 저장하지만, JWT방식은 토큰을 생성하여 응답 합니다. UserAuthenticationFilter(회원검증로직),AuthenticationManager(내부 아이디,비번던져서 로그인검증), JWT는 세션에 회원정보를 남지기 않고 SuccessfulAuthentication라는 메서드에서 토큰을 만들어서 응답으로 보내줄 것 입니다.
개발 환경
- Spring boot 3.2.1
- Security 6.2.1
- Lombok
- Spring Data Jpa -MySQL
- Gradle - Groovy
- IntelliJ Ulitimate
개발환경의 버전의 경우, Java의 버전, Spring boot의 버전에 따라서 구현방식이 조금씩 달라집니다. 이번에는 최신 버전으로 구현해보기위해 Spring boot 3.2.1을 선택합니다. Spring boot 3.2.x 이후의 버전은 Java 17버전부터 사용할 수 있습니다. 그러므로 Java는 17을 사용하겠습니다.
프로젝트 생성
인텔리제이에서 위와같이 프로젝트를 생성해주었습니다.
Java, Gradle-Groovy를 선택해줍니다. Java는 17을 선택합니다.
dependency는 일단 Lombok, Web, Security, JPA, MySQL을 추가해주도록 합니다.
dependency는 프로젝트를 생성하고, 진행하면서 추가해주도록 합니다.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
implementation 'io.jsonwebtoken:jjwt-api:0.12.3' // 추가
implementation 'io.jsonwebtoken:jjwt-impl:0.12.3'
implementation 'io.jsonwebtoken:jjwt-jacson:0.12.3'
}
프로젝트를 생성하고, 위처럼 JWT를 사용하기위해 jjwt를 dependency에 추가해주도록 합니다.
@Controller
@ResponseBody
public class mainController {
@GetMapping("/")
public String main() {
return "main Controller"
}
}
```java
@Controller
@ResponseBody
public class adminController {
@GetMapping("/admin")
public String adminP() {
return "admin Controller"
}
}
간단하게 컨트롤러를 생성해줍니다.
SecurityConfig
SecurityConfig라는 클래스를 만들어줄 것 입니다. 특정한 경로에 요청이 오면 Controller 클래스에 도달하기 전 필터에서 Spring Security가 검증을 합니다.
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
http
.csrf((auth) -> auth.disable());
http
.formLogin((auth) -> auth.disable());
http
.httpBasic((auth) -> auth.disable());
http
.authorizeHttpRequests((auth) -> auth
.requestMatchers("/login", "/", "/join").permitAll()
.requestMatchers("/admin").hasRole("ADMIN")
.anyRequest().authenticated());
http
.sessionManagement((session) -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
return http.build();
}
}
config라는 패키지내에 SecurityConfig라는 클래스를 만들어줍니다. 이 클래스가 springboot에게 configuration으로 관리되기 위해 @Configuration 어노테이션을 붙입니다. security를 위한 config이기 때문에 @EnableWebSecurity를 추가로 붙입니다.
클래스내부에 특정 메소드들을 빈으로 등록해서 security설정을 할 수 있습니다.
인가, 로그인, 세션방법을 사용하기 위해 SecurityFilterChain을 반환하는 filterChain을 메소드를 만듭니다. 인자로 HttpSecurity를 받고, 예외처리를 진행해주도록 Exception을 붙여줍니다. filterChain메서드는 리턴으로 받은 인자를 build해서 리턴합니다. 이제 이 메서드안에서 인증, 로그인, 등등을 구현해주면 된다.
http
.csrf((auth) -> auth.disable());
첫번째로 csrf를 disable해줍니다. 세션방식의 로그인에서는 세션이 고정이기 때문에 csrf에 대해서 방어를 해줘야합니다. 하지만 이번에는 토큰방식으로 할거라서 csrf를 disable해줍니다.
jwt방식으로 로그인 할 것이라서 form 로그인, httpBasic인증방식을 disable합니다. Spring boot 3.1.x ~ 버전 부터는 위처럼 람다형식으로 코드를 짜야합니다.
http
.authorizeHttpRequests((auth) -> auth
.requestMatchers("/login", "/", "/join").permitAll()
.requestMatchers("/admin").hasRole("ADMIN")
.anyRequest().authenticated());
특정 경로에대해 권한 등등의 인가작업을 위해 http에서 authorizeHttpRequest에서 진행할 수 있습니다. 회원가입, 홈 , 로그인은 모두 혀용을 해주고, admin은 ADMIN권한이 있도록 해주고, 나머지경로는 로그인을 해야 접근 가능하도록 해줍시다.
http
.sessionManagement((session) -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
jwt방식에서는 세션을 stateless로 해야합니다. 그러므로 설정해줍니다.
추가적으로 입력받은 비밀번호를 캐시로 암호화시켜서 검증할 것이므로 상단에 BCyptPasswordEncoder를 빈등록 해줍니다.
'Backend > 기능 구현' 카테고리의 다른 글
Spring Security JWT - 4. 로그인 세팅 (0) | 2024.01.17 |
---|---|
Spring Security JWT - 1. 개념 및 동작 방식 (1) | 2024.01.13 |
Spring boot - 멀티 모듈 프로젝트를 만들어보자. (1) | 2024.01.02 |