Skip to content

Commit 3e3ec62

Browse files
authored
[feat] Jwt, Security 설정 및 사용자 정의 예외처리 구현 (#13)
[feat] Jwt, Security 설정 및 사용자 정의 예외처리 구현
2 parents 52e5be7 + 6b004f4 commit 3e3ec62

22 files changed

Lines changed: 707 additions & 1 deletion

.github/workflows/gradle.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ jobs:
4545
echo "DB_URL=${{ secrets.DB_URL }}" > /home/ubuntu/.env
4646
echo "DB_USERNAME=${{ secrets.DB_USERNAME }}" >> /home/ubuntu/.env
4747
echo "DB_PASSWORD=${{ secrets.DB_PASSWORD }}" >> /home/ubuntu/.env
48+
echo "JWT_SECRET=${{ secrets.JWT_SECRET }}" >> /home/ubuntu/.env
4849
4950
docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_TOKEN }}
5051
docker pull kjunh972/dasom_memoreal:latest

.github/workflows/inspect-test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,5 @@ jobs:
2727
DB_URL: ${{ secrets.DB_URL }}
2828
DB_USERNAME: ${{ secrets.DB_USERNAME }}
2929
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
30+
JWT_SECRET: ${{ secrets.JWT_SECRET }}
3031
run: ./gradlew -Dspring.profiles.active=dev test

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,7 @@ out/
3737
.vscode/
3838

3939
### env ###
40-
.env
40+
.env
41+
42+
### macOS ###
43+
.DS_Store

build.gradle

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ repositories {
2424
}
2525

2626
dependencies {
27+
// Security
28+
implementation 'org.springframework.boot:spring-boot-starter-security'
29+
testImplementation 'org.springframework.security:spring-security-test'
30+
31+
//JWT
32+
implementation 'io.jsonwebtoken:jjwt-api:0.12.5'
33+
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.5'
34+
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.5'
35+
36+
2737
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
2838
implementation 'org.springframework.boot:spring-boot-starter-security'
2939
implementation 'org.springframework.boot:spring-boot-starter-web'
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.dasom.MemoReal.domain.user.controller;
2+
3+
import com.dasom.MemoReal.domain.user.dto.JoinDTO;
4+
import com.dasom.MemoReal.domain.user.dto.LoginDTO;
5+
import com.dasom.MemoReal.domain.user.dto.UserDTO;
6+
import com.dasom.MemoReal.domain.user.service.UserService;
7+
import com.dasom.MemoReal.global.jwt.dto.JwtTokenDTO;
8+
import com.dasom.MemoReal.global.security.util.SecurityUtil;
9+
import lombok.RequiredArgsConstructor;
10+
import org.springframework.http.ResponseEntity;
11+
import org.springframework.web.bind.annotation.PostMapping;
12+
import org.springframework.web.bind.annotation.RequestBody;
13+
import org.springframework.web.bind.annotation.RestController;
14+
15+
@RestController
16+
@RequiredArgsConstructor
17+
public class UserController {
18+
private final UserService userService;
19+
20+
@PostMapping("/login")
21+
public JwtTokenDTO login(@RequestBody LoginDTO loginDto) {
22+
String email = loginDto.getEmail();
23+
String password = loginDto.getPassword();
24+
JwtTokenDTO jwtToken = userService.login(email, password);
25+
return jwtToken;
26+
}
27+
28+
@PostMapping("/join")
29+
public ResponseEntity<UserDTO> join(@RequestBody JoinDTO joinDto) {
30+
UserDTO savedUserDto = userService.join(joinDto);
31+
return ResponseEntity.ok(savedUserDto);
32+
}
33+
34+
35+
// 임시 테스트 토큰이 있는 사용자가 요청 시, 사용자의 닉네임 반환
36+
@PostMapping("/test")
37+
public String test() {
38+
return SecurityUtil.getCurrentUsername();
39+
}
40+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.dasom.MemoReal.domain.user.dto;
2+
3+
4+
import com.dasom.MemoReal.domain.user.entity.User;
5+
import lombok.AllArgsConstructor;
6+
import lombok.Builder;
7+
import lombok.Getter;
8+
import lombok.NoArgsConstructor;
9+
10+
import java.util.ArrayList;
11+
import java.util.List;
12+
13+
@Getter
14+
@NoArgsConstructor
15+
@AllArgsConstructor
16+
@Builder
17+
public class JoinDTO {
18+
private String email;
19+
private String password;
20+
private String username;
21+
private List<String> roles = new ArrayList<>();
22+
23+
public User toEntity(String encodedPassword, List<String> roles) {
24+
return User.builder()
25+
.username(username)
26+
.password(encodedPassword)
27+
.email(email)
28+
.roles(roles)
29+
.build();
30+
}
31+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.dasom.MemoReal.domain.user.dto;
2+
3+
import lombok.Getter;
4+
import lombok.NoArgsConstructor;
5+
import lombok.Setter;
6+
import lombok.ToString;
7+
8+
@Getter
9+
@Setter
10+
@ToString
11+
@NoArgsConstructor
12+
public class LoginDTO {
13+
private String email;
14+
private String password;
15+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.dasom.MemoReal.domain.user.dto;
2+
3+
4+
import com.dasom.MemoReal.domain.user.entity.User;
5+
import lombok.*;
6+
7+
@Getter
8+
@ToString
9+
@AllArgsConstructor
10+
@NoArgsConstructor
11+
@Builder
12+
public class UserDTO {
13+
private Long id;
14+
private String email;
15+
private String username;
16+
17+
static public UserDTO toDto(User user) {
18+
return UserDTO.builder()
19+
.id(user.getId())
20+
.username(user.getUsername())
21+
.email(user.getEmail())
22+
.build();
23+
}
24+
25+
public User toEntity() {
26+
return User.builder()
27+
.id(id)
28+
.username(username)
29+
.email(email)
30+
.build();
31+
}
32+
33+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.dasom.MemoReal.domain.user.entity;
2+
3+
import jakarta.persistence.*;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Getter;
7+
import lombok.NoArgsConstructor;
8+
import org.springframework.security.core.GrantedAuthority;
9+
import org.springframework.security.core.authority.SimpleGrantedAuthority;
10+
import org.springframework.security.core.userdetails.UserDetails;
11+
12+
import java.util.ArrayList;
13+
import java.util.Collection;
14+
import java.util.List;
15+
import java.util.stream.Collectors;
16+
17+
@Entity
18+
@Getter
19+
@NoArgsConstructor
20+
@AllArgsConstructor
21+
@Builder
22+
public class User implements UserDetails {
23+
@Id
24+
@GeneratedValue(strategy = GenerationType.IDENTITY)
25+
private Long id;
26+
private String username;
27+
private String password;
28+
private String email;
29+
30+
@ElementCollection(fetch = FetchType.EAGER)
31+
@Builder.Default // 기본값 지정
32+
private List<String> roles = new ArrayList<>();
33+
34+
@Override
35+
public Collection<? extends GrantedAuthority> getAuthorities() {
36+
return this.roles.stream()
37+
.map(SimpleGrantedAuthority::new)
38+
.collect(Collectors.toList());
39+
}
40+
41+
@Override
42+
public boolean isAccountNonExpired() {
43+
return true;
44+
}
45+
46+
@Override
47+
public boolean isAccountNonLocked() {
48+
return true;
49+
}
50+
51+
@Override
52+
public boolean isCredentialsNonExpired() {
53+
return true;
54+
}
55+
56+
@Override
57+
public boolean isEnabled() {
58+
return true;
59+
}
60+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.dasom.MemoReal.domain.user.repository;
2+
3+
import com.dasom.MemoReal.domain.user.entity.User;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
6+
import java.util.Optional;
7+
8+
public interface UserRepository extends JpaRepository<User, Long> {
9+
Optional<User> findByUsername(String username);
10+
Optional<User> findByEmail(String email);
11+
12+
boolean existsByUsername(String username);
13+
}

0 commit comments

Comments
 (0)