Skip to content

Commit

Permalink
Merge pull request #113 from swm-nodriversomabus/BUS-101-Cellphone-Ce…
Browse files Browse the repository at this point in the history
…rtification

Bus 101 cellphone certification
  • Loading branch information
Lemonade255 authored Oct 17, 2023
2 parents 8091351 + 5cf6040 commit 17cf738
Show file tree
Hide file tree
Showing 21 changed files with 370 additions and 10 deletions.
7 changes: 7 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ dependencies {
implementation 'com.google.guava:guava:32.1.2-jre' // google core library 사용
implementation 'org.springframework.boot:spring-boot-starter-security' // security
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'

// implementation(platform("software.amazon.awssdk:bom:2.20.54"))
// implementation 'software.amazon.awssdk:sns' // SNS 모듈 추가
implementation 'com.amazonaws:aws-java-sdk-core:1.11.927'
implementation 'com.amazonaws:aws-java-sdk-sns:1.11.927'
// Spring Boot SNS Starter
// implementation 'org.springframework.boot:spring-boot-starter-aws'
// implementation 'org.springframework.boot:spring-boot-starter-oauth2-client:2.7.11' // oauth2
// implementation 'io.jsonwebtoken:jjwt:0.9.1'
implementation 'org.springframework.boot:spring-boot-starter-web'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public class AuthController {
public ResponseEntity<StatusResponseDto> logout(@CookieValue String access_token, HttpServletResponse response) {
logoutUsecase.removeToken(access_token);

Cookie cookie = new Cookie("accessToken", null);
Cookie cookie = new Cookie("access_token", null);
cookie.setMaxAge(0);
response.addCookie(cookie);
return ResponseEntity.ok(StatusResponseDto.addStatus(200));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Excepti
.requestMatchers("/auth/**").permitAll() // auth로 오는 애들은 일단 인증 없이 가능
.requestMatchers("/actuator/**").permitAll()
.requestMatchers(HttpMethod.POST, "/user/**").permitAll()
.requestMatchers("/sms/**").permitAll()
.requestMatchers("/login/**").permitAll()
.requestMatchers(PERMIT_URL_ARRAY).permitAll()
.anyRequest().authenticated()); // 그 외는 전부 인증 필요
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo
.encode(StandardCharsets.UTF_8)
.toUriString();
log.info("success redirecting");
log.info(targetUrl);
CookieUtils.addCookie(response, "access_token",token.getAccessToken(), 1000 * 60 * 60);
clearAuthenticationAttributes(request, response);
// response.addCookie(CookieUtils.addCookie(););
Expand Down
1 change: 0 additions & 1 deletion src/main/java/com/example/api/auth/type/RefreshToken.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,4 @@ public class RefreshToken implements Serializable { // 직렬화, 역 직렬화
public void updateAccessToken(String accessToken) {
this.accessToken = accessToken;
}

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


import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.sns.AmazonSNSClient;
import com.amazonaws.services.sns.AmazonSNSClientBuilder;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

@Getter
@Configuration
public class AWSConfig {

@Value("${aws.accessKey}")
private String awsAccessKey;

@Value("${aws.secretKey}")
private String awsSecretKey;

@Value("${aws.region}")
private String awsRegion;

@Primary
@Bean
public AmazonSNSClient getAWSSNSClient(){
return (AmazonSNSClient) AmazonSNSClientBuilder.standard()
.withRegion(awsRegion)
.withCredentials(
new AWSStaticCredentialsProvider(new BasicAWSCredentials(awsAccessKey, awsSecretKey))
)
.build();
}
}
5 changes: 3 additions & 2 deletions src/main/java/com/example/api/common/type/ErrorCodeEnum.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
public enum ErrorCodeEnum {
LOGIN_IS_NOT_DONE(HttpStatus.UNAUTHORIZED, "로그인 정보가 없습니다"),
INVALID_PERMISSION(HttpStatus.UNAUTHORIZED, "권한이 없습니다"),
DATABASE_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "데이터베이스 오류");

DATABASE_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "데이터베이스 오류"),
CODE_IS_NOT_VALID(HttpStatus.BAD_REQUEST, "잘못된 인증번호입니다"),
CODE_IS_EXPIRED(HttpStatus.BAD_REQUEST, "휴대전화를 인증해주세요");
private final HttpStatus httpStatus;
private final String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.example.api.sms.adapter.in.rest;

import com.example.api.sms.application.port.in.SendCertificationCodeUsecase;
import com.example.api.sms.application.port.in.VerifyCodeUsecase;
import com.example.api.sms.dto.CheckSMSDto;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/sms")
@Validated
public class SmsController {
private final SendCertificationCodeUsecase sendCertificationCodeUsecase;
private final VerifyCodeUsecase verifyCodeUsecase;

/**
* 핸드폰 인증에 사용
*
* @param phone
*/
@Operation(summary = "certification phone", description = "핸드폰 인증")
@GetMapping("/code/{phone}")
public void sendCertificationPhone(@PathVariable String phone){
sendCertificationCodeUsecase.send(phone);
}

@PostMapping("/code")
public void certificatePhone(@RequestBody @Validated CheckSMSDto checkSMSDto){
verifyCodeUsecase.verifyCertificationCode(checkSMSDto);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.example.api.sms.adapter.out.persistence;


import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
import java.io.Serializable;

/**
* 핸드폰 인증에 사용되는 클래스
*/
@Getter
@AllArgsConstructor
@RedisHash(value = "phone_check", timeToLive = 360) // hash collection 명시
public class PhoneCertification implements Serializable {
@Id
private String phone;
private String code;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.example.api.sms.adapter.out.persistence;


import com.example.api.sms.application.port.out.CertificationCodePort;
import com.example.api.sms.application.port.out.CheckVerifiedPhonePort;
import com.example.api.sms.repository.PhoneCertificationRepository;
import com.example.api.common.exception.CustomException;
import com.example.api.common.type.ErrorCodeEnum;
import com.example.api.sms.repository.VerifyCertificationRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

@Repository
@RequiredArgsConstructor
public class PhoneCertificationPersistence implements CertificationCodePort, CheckVerifiedPhonePort {
private final PhoneCertificationRepository repository;
private final VerifyCertificationRepository verifyCertificationRepository;
@Override
public void saveCode(String phone, String code) {
repository.save(new PhoneCertification(phone, code));
}

@Override
public PhoneCertification findCode(String phone) {
return repository.findById(phone).orElseThrow(()-> new CustomException(ErrorCodeEnum.CODE_IS_EXPIRED));
}

/**
* 인증 번호 만료 여부 확인
* @param phone
*/
@Override
public void findCheckedPhone(String phone) {
verifyCertificationRepository.findById(phone).orElseThrow(()-> new CustomException(ErrorCodeEnum.CODE_IS_EXPIRED));
}

/**
* 인증 여부 저장
* @param phone
*/
@Override
public void saveCheckedPhone(String phone) {
verifyCertificationRepository.save(new VerifyPhoneCertification(phone));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.example.api.sms.adapter.out.persistence;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;

import java.io.Serializable;


/**
* 핸드폰 인증 성공시 한시간 동안 유효하게 냅둠
*/
@Getter
@AllArgsConstructor
@RedisHash(value = "phone_check", timeToLive = 3600) // hash collection 명시
public class VerifyPhoneCertification implements Serializable {
@Id
String phone;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example.api.sms.application.port.in;

import com.amazonaws.services.sns.model.PublishResult;

public interface SendCertificationCodeUsecase {
PublishResult send(String phone);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example.api.sms.application.port.in;

import com.example.api.sms.dto.CheckSMSDto;

public interface VerifyCodeUsecase {
void verifyCertificationCode(CheckSMSDto checkSMSDto);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.example.api.sms.application.port.out;

import com.example.api.sms.adapter.out.persistence.PhoneCertification;

public interface CertificationCodePort {
void saveCode(String phone, String code);

PhoneCertification findCode(String phone);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example.api.sms.application.port.out;

public interface CheckVerifiedPhonePort {
void findCheckedPhone(String phone);

void saveCheckedPhone(String phone);
}
21 changes: 21 additions & 0 deletions src/main/java/com/example/api/sms/dto/CheckSMSDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.example.api.sms.dto;


import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import lombok.Getter;

@Getter
public class CheckSMSDto {
@NotBlank(message = "핸드폰 번호를 입력해주세요")
@Pattern(
regexp = "(01[016789])(\\d{3,4})(\\d{4})",
message = "올바른 핸드폰 번호를 입력해주세요"
)
String phone;

@NotBlank(message = "인증번호를 입력해주세요")
@Pattern(regexp = "^[0-9]{6}$", message = "숫자 6자리만 입력해야 합니다.")
String code;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.example.api.sms.repository;

import com.example.api.sms.adapter.out.persistence.PhoneCertification;
import org.springframework.data.repository.CrudRepository;

import java.util.Optional;

public interface PhoneCertificationRepository extends CrudRepository<PhoneCertification, String> {
// Optional<PhoneCertification> findByPhone(String phone);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.example.api.sms.repository;

import com.example.api.sms.adapter.out.persistence.VerifyPhoneCertification;
import org.springframework.data.repository.CrudRepository;

public interface VerifyCertificationRepository extends CrudRepository<VerifyPhoneCertification, String> {

}
Loading

0 comments on commit 17cf738

Please sign in to comment.