Skip to content

Commit

Permalink
카카오 로그인 기능 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
HwangHoYoon committed Dec 9, 2023
1 parent 78c97fb commit e140d19
Show file tree
Hide file tree
Showing 39 changed files with 1,753 additions and 5 deletions.
57 changes: 57 additions & 0 deletions src/main/generated/com/chwipoClova/common/dto/QToken.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.chwipoClova.common.dto;

import static com.querydsl.core.types.PathMetadataFactory.*;

import com.querydsl.core.types.dsl.*;

import com.querydsl.core.types.PathMetadata;
import javax.annotation.processing.Generated;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.dsl.PathInits;


/**
* QToken is a Querydsl query type for Token
*/
@Generated("com.querydsl.codegen.DefaultEntitySerializer")
public class QToken extends EntityPathBase<Token> {

private static final long serialVersionUID = 1987504615L;

private static final PathInits INITS = PathInits.DIRECT2;

public static final QToken token = new QToken("token");

public final DateTimePath<java.util.Date> modifyDate = createDateTime("modifyDate", java.util.Date.class);

public final StringPath refreshToken = createString("refreshToken");

public final DateTimePath<java.util.Date> regDate = createDateTime("regDate", java.util.Date.class);

public final NumberPath<Long> tokenId = createNumber("tokenId", Long.class);

public final com.chwipoClova.user.entity.QUser user;

public QToken(String variable) {
this(Token.class, forVariable(variable), INITS);
}

public QToken(Path<? extends Token> path) {
this(path.getType(), path.getMetadata(), PathInits.getFor(path.getMetadata(), INITS));
}

public QToken(PathMetadata metadata) {
this(metadata, PathInits.getFor(metadata, INITS));
}

public QToken(PathMetadata metadata, PathInits inits) {
this(Token.class, metadata, inits);
}

public QToken(Class<? extends Token> type, PathMetadata metadata, PathInits inits) {
super(type, metadata, inits);
this.user = inits.isInitialized("user") ? new com.chwipoClova.user.entity.QUser(forProperty("user")) : null;
}

}

49 changes: 49 additions & 0 deletions src/main/generated/com/chwipoClova/user/entity/QUser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.chwipoClova.user.entity;

import static com.querydsl.core.types.PathMetadataFactory.*;

import com.querydsl.core.types.dsl.*;

import com.querydsl.core.types.PathMetadata;
import javax.annotation.processing.Generated;
import com.querydsl.core.types.Path;


/**
* QUser is a Querydsl query type for User
*/
@Generated("com.querydsl.codegen.DefaultEntitySerializer")
public class QUser extends EntityPathBase<User> {

private static final long serialVersionUID = -1980796269L;

public static final QUser user = new QUser("user");

public final StringPath email = createString("email");

public final DateTimePath<java.util.Date> modifyDate = createDateTime("modifyDate", java.util.Date.class);

public final StringPath name = createString("name");

public final DateTimePath<java.util.Date> regDate = createDateTime("regDate", java.util.Date.class);

public final NumberPath<Long> snsId = createNumber("snsId", Long.class);

public final NumberPath<Integer> snsType = createNumber("snsType", Integer.class);

public final NumberPath<Long> userId = createNumber("userId", Long.class);

public QUser(String variable) {
super(User.class, forVariable(variable));
}

public QUser(Path<? extends User> path) {
super(path.getType(), path.getMetadata());
}

public QUser(PathMetadata metadata) {
super(User.class, metadata);
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.chwipoClova.common.config;

import com.chwipoClova.common.exception.ExceptionCode;
import com.chwipoClova.common.response.CommonResponse;
import io.swagger.v3.core.converter.ModelConverters;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.Content;
import io.swagger.v3.oas.models.media.MediaType;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.media.StringSchema;
import io.swagger.v3.oas.models.responses.ApiResponses;
import org.apache.commons.lang3.StringUtils;
import org.springdoc.core.customizers.OperationCustomizer;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.web.method.HandlerMethod;

import java.util.Map;

@Configuration
public class ApiDocsOperationCustomizer implements OperationCustomizer {

@Override
public Operation customize(Operation operation,
HandlerMethod handlerMethod) {
ApiResponses apiResponses = operation.getResponses();
apiResponses.forEach((code, apiResponse) -> {
Content content = operation.getResponses().get(code).getContent();
if (content != null) {
content.keySet().forEach(mediaTypeKey -> {
final MediaType mediaType = content.get(mediaTypeKey);
mediaType.schema(customizeSchema(code, mediaType.getSchema()));
});
}
});
return operation;
}

private Schema<?> customizeSchema(String code, Schema<?> objSchema) {
ModelConverters mc= ModelConverters.getInstance();
Map<String, Schema> read = mc.read(CommonResponse.class);
Schema<?> wrapperSchema = read.get("CommonResponse");

String responseCode;
String responseMessage;

if (StringUtils.equals(code, String.valueOf(HttpStatus.OK.value()))) {
responseCode = String.valueOf(HttpStatus.OK.value());
responseMessage = HttpStatus.OK.getReasonPhrase();
} else {
ExceptionCode exceptionCode = ExceptionCode.resolve(code);
responseCode = exceptionCode.getCode();
responseMessage = exceptionCode.getMessage();
}
wrapperSchema.addProperties("data", objSchema);
wrapperSchema.addProperty("code", new StringSchema()._default(responseCode));
wrapperSchema.addProperty("message", new StringSchema()._default(responseMessage));
return wrapperSchema;
}

}


15 changes: 15 additions & 0 deletions src/main/java/com/chwipoClova/common/config/CommonConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.chwipoClova.common.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class CommonConfig {

@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}

}
141 changes: 141 additions & 0 deletions src/main/java/com/chwipoClova/common/config/JwtProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package com.chwipoClova.common.config;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;

import java.security.Key;
import java.util.Date;

@Slf4j
public class JwtProvider {

private final long ACCESS_TOKEN_EXPIRE_TIME; // 30분
private final long REFRESH_TOKEN_EXPIRE_TIME; // 7일

private final Key key;

public JwtProvider(@Value("${jwt.secret}") String secretKey ,
@Value("${jwt.access-token-expire-time}") long accessTime,
@Value("${jwt.refresh-token-expire-time}") long refreshTime
) {
this.ACCESS_TOKEN_EXPIRE_TIME = accessTime;
this.REFRESH_TOKEN_EXPIRE_TIME = refreshTime;
byte[] keyBytes = Decoders.BASE64.decode(secretKey);
this.key = Keys.hmacShaKeyFor(keyBytes);
}


protected String createToken(String id, long tokenValid) {
// ex) sub : [email protected]
Claims claims = Jwts.claims().setSubject(id);

/* // ex) auth : ROLE_USER,ROLE_ADMIN
claims.put(AUTHORITIES_KEY,
auth.stream()
.map(Authority::getAuthorityName)
.collect(Collectors.joining(","))
);*/

// 현재시간
Date now = new Date();

return Jwts.builder()
.setClaims(claims) // 토큰 발행 유저 정보
.setIssuedAt(now) // 토큰 발행 시간
.setExpiration(new Date(now.getTime() + tokenValid)) // 토큰 만료시간
.signWith(key, SignatureAlgorithm.HS512) // 키와 알고리즘 설정
.compact();
}

/**
*
* @param id
* @return 엑세스 토큰 생성
*/
public String createAccessToken(String id) {
return this.createToken(id, ACCESS_TOKEN_EXPIRE_TIME);
}

/**
*
* @param id
* @return 리프레시 토큰 생성
*/
public String createRefreshToken(String id) {
return this.createToken(id, REFRESH_TOKEN_EXPIRE_TIME);
}

/**
*
* @param token
* @return 토큰 값을 파싱하여 클레임에 담긴 id 값을 가져온다.
*/
public String getMemberIdByToken(String token) {
// 토큰의 claim 의 sub 키에 이메일 값이 들어있다.
return this.parseClaims(token).getSubject();
}

/* public TokenDTO createTokenDTO(String accessToken,String refreshToken) {
return TokenDTO.builder()
.accessToken(accessToken)
.refreshToken(refreshToken)
.grantType(BEARER_TYPE)
.build();
}*/
/*
public Authentication getAuthentication(String accessToken) throws BizException{
// 토큰 복호화
Claims claims = parseClaims(accessToken);
if (claims.get(AUTHORITIES_KEY) == null || !StringUtils.hasText(claims.get(AUTHORITIES_KEY).toString())) {
throw new BizException(AuthorityExceptionType.NOT_FOUND_AUTHORITY); // 유저에게 아무런 권한이 없습니다.
}
log.debug("claims.getAuth = {}",claims.get(AUTHORITIES_KEY));
log.debug("claims.getEmail = {}",claims.getSubject());
// 클레임에서 권한 정보 가져오기
Collection<? extends GrantedAuthority> authorities =
Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(","))
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
authorities.stream().forEach(o->{
log.debug("getAuthentication -> authorities = {}",o.getAuthority());
});
// UserDetails 객체를 만들어서 Authentication 리턴
UserDetails principal = new User(claims.getSubject(), "", authorities);
return new CustomEmailPasswordAuthToken(principal, "", authorities);
}*/

public int validateToken(String token) {
try {
Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token);
return 1;
} catch (ExpiredJwtException e) {
log.info("만료된 JWT 토큰입니다.");
return 2;
} catch (Exception e) {
log.info("잘못된 토큰입니다.");
return -1;
}
}


private Claims parseClaims(String accessToken) {
try {
return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(accessToken).getBody();
} catch (ExpiredJwtException e) { // 만료된 토큰이 더라도 일단 파싱을 함
return e.getClaims();
}
}
}
20 changes: 20 additions & 0 deletions src/main/java/com/chwipoClova/common/config/QueryDslConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.chwipoClova.common.config;

import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class QueryDslConfig {

@PersistenceContext
private EntityManager entityManager;

@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
46 changes: 46 additions & 0 deletions src/main/java/com/chwipoClova/common/config/SwaggerConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.chwipoClova.common.config;

import com.chwipoClova.common.utils.JwtUtil;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI openAPI() {
String key = JwtUtil.ACCESS_TOKEN;
String refreshKey = JwtUtil.REFRESH_TOKEN;

return new OpenAPI()
.addSecurityItem(new SecurityRequirement()
.addList(key)
.addList(refreshKey)
)
.info(apiInfo())
.components(new Components()
.addSecuritySchemes(key, new SecurityScheme()
.name(key)
.type(SecurityScheme.Type.APIKEY)
.in(SecurityScheme.In.HEADER)
.bearerFormat("JWT"))
.addSecuritySchemes(refreshKey, new SecurityScheme()
.name(refreshKey)
.type(SecurityScheme.Type.APIKEY)
.bearerFormat("JWT")
.in(SecurityScheme.In.HEADER))

);
}

private Info apiInfo() {
return new Info()
.title("Springdoc")
.description("Springdoc을 사용한 Swagger UI")
.version("1.0.0");
}
}
Loading

0 comments on commit e140d19

Please sign in to comment.