mirror of
https://github.com/headporter81/specialsource-homepage-backend.git
synced 2026-08-08 15:41:11 +09:00
This commit is contained in:
@@ -46,6 +46,11 @@ dependencies {
|
|||||||
// Jasypt Spring Boot Starter
|
// Jasypt Spring Boot Starter
|
||||||
implementation 'com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.5'
|
implementation 'com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.5'
|
||||||
|
|
||||||
|
// JWT 관련 의존성 (최신 0.12.x 버전 기준)
|
||||||
|
implementation 'io.jsonwebtoken:jjwt-api:0.12.5'
|
||||||
|
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.5'
|
||||||
|
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.5' // JSON 파싱용
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named('test') {
|
tasks.named('test') {
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package company.specialsource.config; // 본인의 패키지 경로에 맞게 수정하세요
|
||||||
|
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import io.jsonwebtoken.JwtException;
|
||||||
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import io.jsonwebtoken.io.Decoders;
|
||||||
|
import io.jsonwebtoken.security.Keys;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JwtTokenProvider {
|
||||||
|
|
||||||
|
private final SecretKey key;
|
||||||
|
private final long expirationTime;
|
||||||
|
|
||||||
|
// application.yml에 적은 설정값들을 생성자를 통해 주입받습니다.
|
||||||
|
public JwtTokenProvider(
|
||||||
|
@Value("${jwt.secret}") String secretKey,
|
||||||
|
@Value("${jwt.expiration-time}") long expirationTime) {
|
||||||
|
|
||||||
|
// Base64로 인코딩된 비밀키를 디코딩하여 실제 암호화 키 객체로 변환합니다.
|
||||||
|
byte[] keyBytes = Decoders.BASE64.decode(secretKey);
|
||||||
|
this.key = Keys.hmacShaKeyFor(keyBytes);
|
||||||
|
this.expirationTime = expirationTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 유저 이름을 받아서 JWT 토큰을 생성하는 메서드
|
||||||
|
public String createToken(String username) {
|
||||||
|
Date now = new Date();
|
||||||
|
Date validity = new Date(now.getTime() + expirationTime);
|
||||||
|
|
||||||
|
return Jwts.builder()
|
||||||
|
.subject(username) // 토큰의 주인(주체) 저장
|
||||||
|
.issuedAt(now) // 토큰 발행 시간
|
||||||
|
.expiration(validity) // 토큰 만료 시간
|
||||||
|
.signWith(key) // 내 서버의 비밀키로 서명(Signature) 생성
|
||||||
|
.compact();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 토큰에서 유저 이름(Subject)을 꺼내는 메서드
|
||||||
|
public String getUsername(String token) {
|
||||||
|
Claims claims = Jwts.parser()
|
||||||
|
.verifyWith(key) // 내 비밀키로 서명을 검증한 뒤
|
||||||
|
.build()
|
||||||
|
.parseSignedClaims(token)
|
||||||
|
.getPayload(); // 데이터 덩어리를 꺼냄
|
||||||
|
|
||||||
|
return claims.getSubject();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 토큰이 유효한지(만료되진 않았는지, 위조되진 않았는지) 검증하는 메서드
|
||||||
|
public boolean validateToken(String token) {
|
||||||
|
try {
|
||||||
|
Jwts.parser()
|
||||||
|
.verifyWith(key)
|
||||||
|
.build()
|
||||||
|
.parseSignedClaims(token);
|
||||||
|
return true; // 아무 에러도 안 나면 정상적인 토큰!
|
||||||
|
} catch (JwtException | IllegalArgumentException e) {
|
||||||
|
// 토큰이 만료되었거나, 위조되었거나, 형식이 잘못되었을 때 여기로 빠집니다.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,26 +1,39 @@
|
|||||||
package company.specialsource.controller;
|
package company.specialsource.controller;
|
||||||
|
|
||||||
|
import company.specialsource.config.JwtTokenProvider;
|
||||||
import company.specialsource.dto.LoginRequest;
|
import company.specialsource.dto.LoginRequest;
|
||||||
import company.specialsource.service.UserService;
|
import company.specialsource.service.UserService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api")
|
@RequestMapping("/api")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor // 롬복이 jwtTokenProvider와 userService의 생성자를 자동으로 만들어줍니다.
|
||||||
public class AuthController {
|
public class AuthController {
|
||||||
|
|
||||||
private final UserService userService;
|
private final JwtTokenProvider jwtTokenProvider;
|
||||||
|
private final UserService userService; // 실제 서비스 주입
|
||||||
|
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
public ResponseEntity<String> login(@RequestBody LoginRequest loginRequest) {
|
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
|
||||||
boolean isSuccess = userService.login(loginRequest.getUsername(), loginRequest.getPassword());
|
|
||||||
|
|
||||||
if (isSuccess) {
|
// 1. 기존 하드코딩("admin", "1234") 대신 실제 DB를 조회하는 서비스 메서드 호출
|
||||||
return ResponseEntity.ok("로그인 성공!!!");
|
if (userService.login(request.getUsername(), request.getPassword())) {
|
||||||
} else {
|
|
||||||
|
// 2. 로그인 성공 시, 입력받은 username으로 JWT 토큰 생성
|
||||||
|
String token = jwtTokenProvider.createToken(request.getUsername());
|
||||||
|
|
||||||
|
// 3. 응답 상자에 토큰을 담아서 리턴
|
||||||
|
Map<String, String> response = new HashMap<>();
|
||||||
|
response.put("token", token);
|
||||||
|
return ResponseEntity.ok(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. DB에 유저가 없거나 비밀번호가 틀리면 401 반환
|
||||||
return ResponseEntity.status(401).body("아이디 또는 비밀번호가 틀렸습니다.");
|
return ResponseEntity.status(401).body("아이디 또는 비밀번호가 틀렸습니다.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
package company.specialsource.dto;
|
package company.specialsource.dto; // 패키지 위치에 맞게 조정하세요
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
@Getter @Setter
|
|
||||||
public class LoginRequest {
|
public class LoginRequest {
|
||||||
private String username;
|
private String username;
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
|
// Getter, Setter (인텔리제이에서 롬복 @Getter, @Setter 쓰셔도 됩니다!)
|
||||||
|
public String getUsername() { return username; }
|
||||||
|
public void setUsername(String username) { this.username = username; }
|
||||||
|
public String getPassword() { return password; }
|
||||||
|
public void setPassword(String password) { this.password = password; }
|
||||||
}
|
}
|
||||||
@@ -16,3 +16,9 @@ spring:
|
|||||||
jasypt:
|
jasypt:
|
||||||
encryptor:
|
encryptor:
|
||||||
password: 81sungjin1015
|
password: 81sungjin1015
|
||||||
|
|
||||||
|
jwt:
|
||||||
|
# 256비트 이상이어야 하므로 영문+숫자 (최소 32글자 이상)
|
||||||
|
secret: c3ByaW5nYm9vdC1qd3Qtc2VjcmV0LWtleS1zcGVjaWFsc291cmNlLWhvbWVwYWdlLWJhY2tlbmQtMjAyNg==
|
||||||
|
# 토큰 유효 시간 (1시간으로 설정 = 60분 * 60초 * 1000밀리초)
|
||||||
|
expiration-time: 3600000
|
||||||
Reference in New Issue
Block a user