Skip to content

Commit

Permalink
Merge pull request #95 from Kek-i/feature/8-users-auth
Browse files Browse the repository at this point in the history
  • Loading branch information
sojungpp authored Jan 27, 2023
2 parents 903762b + f0cb6cb commit 5de3aba
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/main/java/com/codepatissier/keki/common/Role.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
public enum Role {
CUSTOMER(1, "구매자"),
STORE(2, "판매자"),
ADMIN(3, "비회원");
ANONYMOUS(3, "비회원");

private int number;
private String name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import javax.servlet.http.HttpSession;
import java.net.URISyntaxException;

import static com.codepatissier.keki.common.BaseResponseStatus.SUCCESS;

@SecurityRequirement(name = "Bearer")
@Tag(name = "users", description = "구매자 API")
@RestController
Expand All @@ -27,6 +29,7 @@ public class UserController {
private final AuthService authService;
private final NaverService naverService;
private final KakaoService kakaoService;
private final GoogleService googleService;

// 카카오 로그인 url 요청
@GetMapping("/login/kakao")
Expand Down Expand Up @@ -63,6 +66,23 @@ public BaseResponse<?> naverCallback(@RequestParam String code, HttpSession sess
}
}

// 구글 로그인 url 요청
@GetMapping("/login/google")
public BaseResponse<?> googleLogin(HttpSession session) {
String httpHeaders = googleService.getAuthorizationUrl(session);
return new BaseResponse<>(httpHeaders);
}

// 구글 로그인 콜백
@GetMapping("/callback/google")
public BaseResponse<?> googleCallback(@RequestParam String code, HttpSession session) {
try{
return new BaseResponse<>(userService.googleLogin(code, session));
}catch (BaseException e){
return new BaseResponse<>(e.getStatus());
}
}

// 프론트로부터 이메일만 받아오는 경우 로그인
@ResponseBody
@PostMapping("/signin")
Expand Down Expand Up @@ -93,7 +113,7 @@ public BaseResponse<?> signup(@RequestBody PostCustomerReq postCustomerReq) {
public BaseResponse<?> checkNickname(@RequestBody PostNicknameReq postNicknameReq) {
try{
userService.checkNickname(postNicknameReq);
return new BaseResponse<>(BaseResponseStatus.SUCCESS);
return new BaseResponse<>(SUCCESS);
}catch (BaseException e){
return new BaseResponse<>(e.getStatus());
}
Expand All @@ -117,7 +137,31 @@ public BaseResponse<?> modifyProfile(@RequestBody PatchProfileReq patchProfileRe
try{
Long userIdx = authService.getUserIdx();
userService.modifyProfile(userIdx, patchProfileReq);
return new BaseResponse<>(BaseResponseStatus.SUCCESS);
return new BaseResponse<>(SUCCESS);
}catch (BaseException e){
return new BaseResponse<>(e.getStatus());
}
}

// 회원 탈퇴
@PatchMapping("/signout")
public BaseResponse<?> signout() {
try{
Long userIdx = authService.getUserIdx();
userService.signout(userIdx);
return new BaseResponse<>(SUCCESS);
}catch (BaseException e){
return new BaseResponse<>(e.getStatus());
}
}

// 회원 로그아웃
@PatchMapping("/logout")
public BaseResponse<?> logout() {
try{
Long userIdx = authService.getUserIdx();
userService.logout(userIdx);
return new BaseResponse<>(SUCCESS);
}catch (BaseException e){
return new BaseResponse<>(e.getStatus());
}
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/com/codepatissier/keki/user/dto/GoogleLogin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.codepatissier.keki.user.dto;

import com.github.scribejava.core.builder.api.DefaultApi20;

public class GoogleLogin extends DefaultApi20{

protected GoogleLogin(){
}

private static class InstanceHolder{
private static final GoogleLogin INSTANCE = new GoogleLogin();
}

public static GoogleLogin instance(){
return InstanceHolder.INSTANCE;
}

@Override
public String getAccessTokenEndpoint() {
return "https://www.googleapis.com/oauth2/v4/token";
}

@Override
protected String getAuthorizationBaseUrl() {
return "https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&prompt=consent";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

@Getter
public enum Provider {
GOOGLE, KAKAO, NAVER
GOOGLE, KAKAO, NAVER, ANONYMOUS
}
18 changes: 18 additions & 0 deletions src/main/java/com/codepatissier/keki/user/entity/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,22 @@ public void setProfileImg(String profileImg) {
public void setNickname(String nickname) {
this.nickname = nickname;
}

// 회원 탈퇴
public void signout() {
this.nickname = "알 수 없음";
this.email = "anonymous@keki.store";
this.provider = Provider.ANONYMOUS;
this.profileImg = null;
this.refreshToken = null;
this.role = Role.ANONYMOUS;
this.setStatus("inactive");
// TODO status enum으로 변경
}

// 회원 로그아웃
public void logout() {
this.refreshToken = null;
this.setStatus("logout");
}
}
110 changes: 110 additions & 0 deletions src/main/java/com/codepatissier/keki/user/service/GoogleService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package com.codepatissier.keki.user.service;

import com.codepatissier.keki.user.dto.GoogleLogin;
import com.github.scribejava.core.builder.ServiceBuilder;
import com.github.scribejava.core.oauth.OAuth20Service;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.nimbusds.jose.shaded.json.parser.ParseException;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpSession;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;


@Service
@RequiredArgsConstructor
public class GoogleService {

@Value("${google.client-id}")
private String client_id;

@Value("${google.redirect_uri}")
private String redirect_uri;

@Value("${google.client-secret}")
private String client_secret;

private final static String USER_INFO_URL = "https://www.googleapis.com/userinfo/v2/me?access_token=";
private final static String ACCESS_TOKEN_URL = "https://www.googleapis.com/oauth2/v4/token";

public String getAuthorizationUrl(HttpSession session) {
OAuth20Service oauthService = new ServiceBuilder()
.apiKey(client_id)
.apiSecret(client_secret)
.callback(redirect_uri)
.scope("email")
.build(GoogleLogin.instance());

return oauthService.getAuthorizationUrl();
}

public String getAccessToken(HttpSession session, String authorize_code) throws IOException {
String access_Token = "";

try {
URL url = new URL(ACCESS_TOKEN_URL);

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setRequestMethod("POST");
conn.setDoOutput(true);

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
StringBuilder sb = new StringBuilder();
sb.append("grant_type=authorization_code");

sb.append("&client_id="+client_id);
sb.append("&client_secret="+client_secret);
sb.append("&redirect_uri="+redirect_uri);
sb.append("&code="+authorize_code);
bw.write(sb.toString());
bw.flush();

BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = "";
String result = "";

while ((line = br.readLine()) != null) {
result += line;
}

JsonParser parser = new JsonParser();
JsonElement element = parser.parse(result);
access_Token = element.getAsJsonObject().get("access_token").getAsString();
br.close();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
return access_Token;
}

public String getUserInfo(String access_Token) throws IOException, ParseException {
String reqURL = USER_INFO_URL+access_Token;
try {
URL url = new URL(reqURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", "Bearer " + access_Token);

BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = "";
String result = "";
while ((line = br.readLine()) != null) {
result += line;
}
JsonParser parser = new JsonParser();
JsonElement element = parser.parse(result);
String email = element.getAsJsonObject().get("email").getAsString();
return email;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class UserService {
private final AuthService authService;
private final KakaoService kakaoService;
private final NaverService naverService;
private final GoogleService googleService;

// 카카오 로그인
public PostUserRes kakaoLogin(String authorize_code) throws BaseException{
Expand All @@ -49,6 +50,19 @@ public PostUserRes naverLogin(String code, HttpSession session) throws BaseExcep
}
}

// 구글 로그인
public PostUserRes googleLogin(String code, HttpSession session) throws BaseException{
try {
String googleToken = googleService.getAccessToken(session, code);
String userEmail = googleService.getUserInfo(googleToken);
return signInOrUp(userEmail, Provider.GOOGLE);
} catch (BaseException e) {
throw e;
} catch (Exception e) {
throw new BaseException(DATABASE_ERROR);
}
}

// 회원가입 또는 기존 로그인
private PostUserRes signInOrUp(String userEmail, Provider provider) throws BaseException {
boolean is_user = userRepository.existsByEmail(userEmail);
Expand All @@ -63,7 +77,7 @@ private User signup(String email, Provider provider) {
User newUser = User.builder()
.email(email)
.provider(provider)
.role(Role.ADMIN)
.role(Role.ANONYMOUS)
.build();
return userRepository.save(newUser);
}
Expand Down Expand Up @@ -123,4 +137,32 @@ public void modifyProfile(Long userIdx, PatchProfileReq patchProfileReq) throws
}

}

// 회원 탈퇴
@Transactional
public void signout(Long userIdx) throws BaseException {
try{
User user = userRepository.findById(userIdx).orElseThrow(() -> new BaseException(INVALID_USER_IDX));
user.signout();
// TODO redis 사용해 토큰 관리
} catch (BaseException e) {
throw e;
} catch (Exception e) {
throw new BaseException(DATABASE_ERROR);
}
}

// 회원 로그아웃
@Transactional
public void logout(Long userIdx) throws BaseException {
try{
User user = userRepository.findById(userIdx).orElseThrow(() -> new BaseException(INVALID_USER_IDX));
user.logout();
// TODO redis 사용해 토큰 관리
} catch (BaseException e) {
throw e;
} catch (Exception e) {
throw new BaseException(DATABASE_ERROR);
}
}
}

0 comments on commit 5de3aba

Please sign in to comment.