Skip to content

Commit

Permalink
Merge pull request #27 from T1F5/feature/#25
Browse files Browse the repository at this point in the history
feat: LoginUser 정상 호출
  • Loading branch information
char-yb authored Apr 6, 2024
2 parents 5c1ab64 + 141f7d9 commit 3fedeff
Show file tree
Hide file tree
Showing 10 changed files with 214 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.unit.daybook.domain.auth.service;

import java.time.Duration;
import java.time.LocalDateTime;

import org.springframework.stereotype.Service;

import com.unit.daybook.domain.auth.common.OAuthInfoResponse;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.unit.daybook.domain.auth.service;

import java.time.Duration;
import java.time.LocalDateTime;

import org.springframework.stereotype.Component;

import com.unit.daybook.domain.auth.dto.response.SocialLoginResponse;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
public class TokenService {
private static final Long DEFAULT_EXPIRATION_MINUTES = 60L;

@Value("${jwt.secret-key}")
@Value("${util.jwt.secretKey}")
private String secretKey;

private static SecretKey createSecretKey(String key) {
Expand All @@ -42,7 +42,7 @@ private static SecretKey createSecretKey(String key) {
}

public static String parseTokenByRequest(HttpServletRequest request) {
final String authHeader = request.getHeader("authorization");
final String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
return authHeader.substring(7);
}
Expand Down Expand Up @@ -126,12 +126,12 @@ public CustomUserDetails getUserDetailsByToken(String token) {

// token정보 이외에 추가로 정보가 필요해서 DB의 데이터를 조회해서 userDetails정보를 만드려면 UserDetailsService 인터페이스를 캐시서비스 또는 유저서비스에서 구현해서 userDetails를 리턴하게 하면 된다.
// 꼭 UserDetailsService 인터페이스를 구현하지 않아도 되고 DB를 조회해서 userDetails에 데이터를 넣어서 리턴해주게 만들면된다.
Long userId = Long.parseLong(claims.get("memberId").toString());
String userSnsId = claims.get("snsId") != null ? claims.get("snsId").toString() : null;
String userEmail = claims.get("email") != null ? claims.get("email").toString() : null;
String userNickname = claims.get("nickname").toString();
Long memberId = Long.parseLong(claims.get("memberId").toString());
String snsId = claims.get("snsId") != null ? claims.get("snsId").toString() : null;
String email = claims.get("email") != null ? claims.get("email").toString() : null;
String nickname = claims.get("nickname").toString();

return new CustomUserDetails(userId, userSnsId, userEmail, userNickname);
return new CustomUserDetails(memberId, snsId, email, nickname);
}


Expand Down Expand Up @@ -162,13 +162,21 @@ private String generateRefreshToken(Map<String, Object> claims, SecretKey key) {
* @return
*/
private Map<String, Object> getClaims(String jwt) {
if (jwt == null || jwt.isEmpty()) {
try {
if (jwt == null || jwt.isEmpty()) {
return null;
}
SecretKey key = createSecretKey(secretKey);
return Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(jwt)
.getBody();
} catch (Exception e) {
// 예외 처리
e.printStackTrace();
return null;
}
return Jwts.parserBuilder()
.setSigningKey(secretKey)
.build()
.parseClaimsJws(jwt)
.getBody();
}

}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.unit.daybook.domain.member.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.unit.daybook.domain.common.annotation.LoginUsers;
import com.unit.daybook.domain.member.domain.Member;
import com.unit.daybook.domain.member.service.MemberService;
import com.unit.daybook.global.config.security.CustomUserDetails;

import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
@RequestMapping("/member")
public class MemberController {

private final MemberService memberService;

@GetMapping
public Member memberFindOne(
@LoginUsers CustomUserDetails userDetails
) {
return memberService.findOneMember(userDetails.getMemberId());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.unit.daybook.domain.member.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.unit.daybook.domain.member.domain.Member;
import com.unit.daybook.domain.member.repository.MemberRepository;
import com.unit.daybook.global.config.security.CustomUserDetails;
import com.unit.daybook.global.error.exception.CustomException;
import com.unit.daybook.global.error.exception.ErrorCode;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
@Transactional
public class MemberService {

private final MemberRepository memberRepository;

@Transactional(readOnly = true)
public Member findOneMember(Long memberId) {
return memberRepository.findById(memberId)
.orElseThrow(() -> new CustomException(ErrorCode.MEMBER_NOT_FOUND));
}
}
36 changes: 36 additions & 0 deletions src/main/java/com/unit/daybook/global/config/WebMvcConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.unit.daybook.global.config;

import java.util.Arrays;
import java.util.List;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.unit.daybook.global.config.resolver.LoginUserDetailsResolver;

import lombok.RequiredArgsConstructor;

@Configuration
@RequiredArgsConstructor
public class WebMvcConfig implements WebMvcConfigurer {

private final LoginUserDetailsResolver loginUserDetailsResolver;

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(loginUserDetailsResolver);
}

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods(Arrays.stream(HttpMethod.values())
.map(HttpMethod::name)
.toArray(String[]::new))
.allowedHeaders("*");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ public class CustomUserDetails implements UserDetails {
private final String nickname;
private final List<GrantedAuthority> authorityList;

public CustomUserDetails(Long memberId, String snsId, String email, String userNickname) {
public CustomUserDetails(Long memberId, String snsId, String email, String nickname) {
this.memberId = memberId;
this.snsId = snsId;
this.authorityList = new ArrayList<>();
this.email = email;
this.nickname = userNickname;
this.nickname = nickname;
}

@Override
Expand Down Expand Up @@ -61,8 +61,5 @@ public boolean isEnabled() {
return true;
}

public void setUserId(Long userId) {
this.memberId = userId;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ public enum ErrorCode {
KAKAO_RESPONSE_NOT_FOUND(HttpStatus.UNAUTHORIZED, "카카오에 대한 응답값이 존재하지 않습니다."),
CLAIMS_IS_NULL(HttpStatus.UNAUTHORIZED, "Claim이 null 값입니다."),
INVALID_TOKEN(HttpStatus.UNAUTHORIZED, "유효하지 않는 토큰입니다."),
;
EXPIRED_REFRESH_TOKEN(HttpStatus.FORBIDDEN, "리프레시 토큰이 만료되었습니다."),

// Member
MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 회원입니다.");
private final HttpStatus status;
private final String message;
}
91 changes: 91 additions & 0 deletions src/main/java/com/unit/daybook/global/util/JwtUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package com.unit.daybook.global.util;

import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Base64;
import java.util.Map;

import javax.crypto.SecretKey;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwsHeader;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;

@Component
public class JwtUtil {

@Value("${util.jwt.secretKey}")
private String jwtSecretKey;

@Value("${util.jwt.refreshKey}")
private String jwtReFreshKey;
private byte[] secretBytes;
private byte[] refreshBytes;

/**
* JWT 생성
*
* @param claims
* @return
*/
public String generateToken(Map<String, Object> claims) {
return Jwts.builder()
.setClaims(claims)
.signWith(SignatureAlgorithm.HS256, secretBytes)
.compact();
}

public String generateRefreshToken(Map<String, Object> claims) {
return Jwts.builder()
.setClaims(claims)
.signWith(SignatureAlgorithm.HS256, refreshBytes)
.compact();
}

public String generateToken(Map<String, Object> header, Map<String, Object> claims, Key key) {
return Jwts.builder()
.setHeader(header)
.setClaims(claims)
.signWith(SignatureAlgorithm.valueOf(header.get(JwsHeader.ALGORITHM).toString()), key)
.compact();
}

/**
* JWT 검증 및 데이터 가져오기
*
* @param jwt
* @return
*/
public Map<String, Object> getClaims(String jwt) {
try {
if (jwt == null || jwt.isEmpty()) {
return null;
}
Claims claims = Jwts.parser()
.setSigningKey(jwtSecretKey)
.parseClaimsJws(jwt)
.getBody();
return claims;
} catch (Exception e) {
// 예외 처리
e.printStackTrace();
return null;
}
}

public Map<String, Object> getClaimsForReFresh(String jwt) {
if (jwt == null || jwt.isEmpty()) {
return null;
}
return Jwts.parser()
.setSigningKey(jwtReFreshKey)
.parseClaimsJws(jwt)
.getBody();
}
}

0 comments on commit 3fedeff

Please sign in to comment.