Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: 구글로그인 성공 후 memberId, isActive 반환 #112

Merged
merged 17 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 134 additions & 14 deletions src/main/java/inandout/backend/Util/EmailUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,63 @@ public void sendEmail(Member member) {

try {
message.addRecipients(MimeMessage.RecipientType.TO, receiverMail);// 보내는 대상
message.setSubject("in&out 회원가입 이메일 인증");// 제목
message.setSubject("In&Out 회원가입 이메일 인증");// 제목

log.info(member.getAuthToken());
log.info(email);
log.info("이메일 인증");

String body = "<div>"
+ "<h1> 안녕하세요. in&out 입니다</h1>"
+ "<br>"
+ "<p>아래 링크를 클릭하면 이메일 인증이 완료됩니다.<p>"
+ "<a href='" + requestUri + member.getAuthToken() + "'>인증 링크</a>"
+ "</div>";
String body = "<body>" +
" <div style=\"width: 592px\">" +
" <img" +
" src=\"https://inandout-bucket.s3.ap-northeast-2.amazonaws.com/logo.svg\"" +
" />\n" +
" <div style=\"margin: 0 20px\">" +
" <div style=\"font-size: 40px; font-weight: 700; margin-top: 32px\">" +
" 회원가입을 위한<br />" +
" 가장 마지막 절차예요!" +
" </div>" +
" <div" +
" style=\"" +
" color: #b4b4b4;" +
" font-size: 22px;" +
" font-weight: 500;" +
" margin-top: 16px;" +
" \"" +
" >" +
" 메일 확인과 개인정보보호를 위해 인증절차를 진행하고 있어요.<br />" +
" 인증 버튼을 눌러 회원가입을 완료해주세요." +
" </div>" +
" <a href='\"" + requestUri + member.getAuthToken() + "\"'>" +
" <button" +
" style=\"" +
" margin-top: 80px;" +
" background-color: black;" +
" color: white;" +
" border: none;" +
" border-radius: 99px;" +
" width: 100%;" +
" height: 80px;" +
" font-size: 22px;" +
" cursor: pointer;" +
" \"" +
" >" +
" 메일 인증하기" +
" </button>" +
" </a>" +
" <div" +
" style=\"" +
" color: #b4b4b4;" +
" font-size: 22px;" +
" font-weight: 500;" +
" margin-top: 120px;" +
" \"" +
" >" +
" * 본 메일은 발신전용으로 회신이 불가능합니다." +
" </div>" +
" </div>" +
" </div>" +
" </body>";

message.setText(body, "utf-8", "html");// 내용, charset 타입, subtype
// 보내는 사람의 이메일 주소, 보내는 사람 이름
Expand All @@ -60,16 +106,90 @@ public void sendPasswordEmail(String email, String newPwd) {

try {
message.addRecipients(MimeMessage.RecipientType.TO, receiverMail);// 보내는 대상
message.setSubject("in&out 비밀번호 찾기");// 제목
message.setSubject("In&Out 비밀번호 찾기");// 제목

log.info(email);

String body = "<div>"
+ "<h1> 안녕하세요. in&out 입니다</h1>"
+ "<br>"
+ "<p>아래의 임시 비밀번호로 회원가입 하세요.<p>"
+ "<p>" + newPwd +"<p>"
+ "</div>";
String body = "<div style=\"width: 592px\">\n" +
" <img\n" +
" src=\"https://inandout-bucket.s3.ap-northeast-2.amazonaws.com/logo.svg\"\n" +
" />\n" +
" <div style=\"margin: 0 20px\">\n" +
" <div style=\"font-size: 40px; font-weight: 700; margin-top: 32px\">\n" +
" 요청하신\n" +
" <br />\n" +
" 임시 비밀번호가 발급됐어요\n" +
" </div>\n" +
" <div\n" +
" style=\"\n" +
" color: #b4b4b4;\n" +
" font-size: 22px;\n" +
" font-weight: 500;\n" +
" margin-top: 16px;\n" +
" \"\n" +
" >\n" +
" 개인정보보호를 위해 임시 비밀번호는 꼭 변경해주세요.\n" +
" </div>\n" +
"\n" +
" <div\n" +
" style=\"\n" +
" background-color: #fce9e0;\n" +
" display: flex;\n" +
" padding: 24px 0px;\n" +
" flex-direction: column;\n" +
" justify-content: center;\n" +
" align-items: center;\n" +
" gap: 12px;\n" +
" align-self: stretch;\n" +
" margin-top: 80px;\n" +
" \"\n" +
" >\n" +
" <div style=\"font-size: 22px; color: #898989; font-weight: 500\">\n" +
" 임시비밀번호\n" +
" </div>\n" +
" <div\n" +
" style=\"\n" +
" color: #000;\n" +
" font-size: 56px;\n" +
" font-style: normal;\n" +
" font-weight: 500;\n" +
" line-height: 56px;\n" +
" \"\n" +
" >\n" +
" " + newPwd + "\n" +
" </div>\n" +
" </div>\n" +
"\n" +
" <a href=\"http://stuffinout.site/login\">\n" +
" <button\n" +
" style=\"\n" +
" margin-top: 80px;\n" +
" background-color: black;\n" +
" color: white;\n" +
" border: none;\n" +
" border-radius: 99px;\n" +
" width: 100%;\n" +
" height: 80px;\n" +
" font-size: 22px;\n" +
" font-weight: 500;\n" +
" cursor: pointer;\n" +
" \"\n" +
" >\n" +
" 인앤아웃 로그인하러 가기\n" +
" </button>\n" +
" </a>\n" +
" <div\n" +
" style=\"\n" +
" color: #b4b4b4;\n" +
" font-size: 22px;\n" +
" font-weight: 500;\n" +
" margin-top: 100px;\n" +
" \"\n" +
" >\n" +
" * 본 메일은 발신전용으로 회신이 불가능합니다.\n" +
" </div>\n" +
" </div>\n" +
" </div>";

message.setText(body, "utf-8", "html");// 내용, charset 타입, subtype
// 보내는 사람의 이메일 주소, 보내는 사람 이름
Expand Down
20 changes: 10 additions & 10 deletions src/main/java/inandout/backend/config/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,19 +69,21 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((auth) -> auth
// TODO: 공유 URL만 경로 모든 권한 허용해주기
// 모든 권한 허용
.requestMatchers("/login", "/", "/join", "/healthcheck", "/regenerate-token", "/find-password", "/logout",
"/auth/verify", "/kakaologin/callback", "/inout", "/myroom", "/others/room", "/kakaologin", "/others", "/user/modify",
"/ws/chat", "/chat", "/oauth2/authorization/google", "/login/oauth2/code/google", "/myroom/link", "/myroom/post","/link", "/kakaologin/local", "/kakaologin/nickname").permitAll()
.requestMatchers("/login", "/", "/join", "/healthcheck", "/regenerate-token", "/find-password",
"/auth/verify", "/kakaologin/callback", "/kakaologin", "/kakaologin/local",
"/oauth2/authorization/google", "/login/oauth2/code/google", "/myroom", "/myroom/post").permitAll()

.requestMatchers( "/myroom").anonymous()
// .requestMatchers( "/myroom", "/myroom/post/{postId}").anonymous()

// "ADMIN"이라는 권한을 가진 사용자만 접근 가능
.requestMatchers("/admin").hasRole("ADMIN")
// 로그인 한 사용자만 접근 가능, 즉 Header에 Authorization이 있는 경로만 허용
.requestMatchers("/main", "/ispublic", "/password", "/check-password", "/nickname",
"/myroom/chat","/myroom/post/{postId}/chat",
"/others/room/detail/{postId}/chat", "/myroom/addstuff",
"/myroom/post/{postId}","/others","/others/post/{postId}","/myroom/updatestuff", "/myroom/link", "/myroom/post","/myroom/post/{postId}" ).authenticated());
.requestMatchers("/main", "/password", "/check-password", "/nickname", "/logout",
"/others", "/others/room", "/others/room/detail/{postId}/chat", "/others/post/{postId}",
"/myroom/chat","/myroom/post/{postId}/chat", "/myroom/addstuff", "/myroom/updatestuff",
"/myroom/link", "/link", "/myroom/post/{postId}",
"/ispublic", "/inout", "/user/modify",
"/ws/chat", "/chat").authenticated());


//LoginFilter 이전에 JWTFilter 등록
Expand All @@ -90,8 +92,6 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
//필터 추가 LoginFilter()는 인자를 받음 (AuthenticationManager() 메소드에 authenticationConfiguration 객체를 넣어야 함) 따라서 등록 필요
http.addFilterAt(new LoginFilter(memberRepository, authenticationManager(authenticationConfiguration), jwtUtil, redisService), UsernamePasswordAuthenticationFilter.class);



//세션 설정
http.sessionManagement((session) -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); // 세션을 STATELESS 상태로 설정
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,22 +133,22 @@ public ResponseEntity<KakoLoginResponseDTO> KakaoLoginCallBack(@RequestParam(val

}

@PostMapping("/nickname")
public BaseResponse KakaoLoginNickname(@RequestBody KakaoNicknameRequestDTO kakaoNicknameRequestDTO) {
System.out.println("KakaoLoginController/KakaoLoginNickname");
Integer memberId = kakaoNicknameRequestDTO.getMemberId();
String nickname = kakaoNicknameRequestDTO.getNickname();

//닉네임 중복 확인
if (memberService.isDuplicateNickname(nickname, memberId)) {
// 중복
BaseException baseException = new BaseException(DUPLICATED_NICKNAME);
throw new MemberException(DUPLICATED_NICKNAME);
}

// 닉네임 변환 & ACTIVE로 변환
memberService.updateNickname(memberId, nickname);

return new BaseResponse("success");
}
// @PostMapping("/nickname")
// public BaseResponse KakaoLoginNickname(@RequestBody KakaoNicknameRequestDTO kakaoNicknameRequestDTO) {
// System.out.println("KakaoLoginController/KakaoLoginNickname");
// Integer memberId = kakaoNicknameRequestDTO.getMemberId();
// String nickname = kakaoNicknameRequestDTO.getNickname();
//
// //닉네임 중복 확인
// if (memberService.isDuplicateNickname(nickname, memberId)) {
// // 중복
// BaseException baseException = new BaseException(DUPLICATED_NICKNAME);
// throw new MemberException(DUPLICATED_NICKNAME);
// }
//
// // 닉네임 변환 & ACTIVE로 변환
// memberService.setNickname(memberId, nickname);
//
// return new BaseResponse("success");
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class MemberController {
public BaseResponse<String> setNickname(@MemberId Integer memberId, @RequestBody NicknameDTO nickname) {
System.out.println("들어옴");
System.out.println("email:::: "+memberId);
memberService.updateNickname(memberId, nickname.getNickname());
memberService.setNickname(memberId, nickname.getNickname());
return new BaseResponse<>("닉네임 설정이 완료되었습니다.");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import inandout.backend.common.response.BaseErrorResponse;
import inandout.backend.common.response.BaseResponse;
import inandout.backend.dto.myroom.*;
import inandout.backend.dto.post.PostIdRequest;
import inandout.backend.jwt.JWTUtil;
import inandout.backend.service.myroom.MyRoomService;
import inandout.backend.service.myroom.S3Service;
Expand Down Expand Up @@ -63,15 +64,15 @@ public BaseResponse<MyRoomAddStuffResponseDTO> myRoomAddStuffController(@Request
}

@GetMapping("/myroom/post")
public BaseResponse<PostResponseDTO> getPostAnonymousController(@RequestParam(value = "postId") Integer postId) {
System.out.println("postId; "+postId);
public BaseResponse<PostResponseDTO> getPostAnonymousController(@RequestParam(value = "postId") String postId) {
System.out.println("postId; "+Integer.parseInt(postId));
System.out.println("MyRoomController/getPostAnonymousController");
Integer memberId = -1;

PostResponseDTO postResponseDTO = postService.getPost(memberId, postId);
PostResponseDTO postResponseDTO = postService.getPost(memberId, Integer.parseInt(postId));

//조회수 up
postService.plusUserCount(postId);
postService.plusUserCount(Integer.parseInt(postId));

return new BaseResponse<>(postResponseDTO);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,14 @@ public Integer getMemberId() {

return userDTO.getMemberId();
}

public Boolean getIsActive() {

return userDTO.getIsActive();
}

public Integer getImageId() {

return userDTO.getImageId();
}
}
6 changes: 5 additions & 1 deletion src/main/java/inandout/backend/dto/login/oauth2/UserDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@
public class UserDTO {
private Integer memberId;
private String email;
private Boolean isActive;
private Integer imageId;

public UserDTO(Integer memberId, String email) {
public UserDTO(Integer memberId, String email, Boolean isActive, Integer imageId) {
this.memberId = memberId;
this.email = email;
this.isActive = isActive;
this.imageId = imageId;
}
}
8 changes: 8 additions & 0 deletions src/main/java/inandout/backend/dto/post/PostIdRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package inandout.backend.dto.post;

import lombok.Getter;

@Getter
public class PostIdRequest {
private Integer postId;
}
19 changes: 17 additions & 2 deletions src/main/java/inandout/backend/jwt/CustomSuccessHandler.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package inandout.backend.jwt;

import inandout.backend.dto.login.oauth2.CustomOauth2User;
import inandout.backend.repository.login.MemberRepository;
import inandout.backend.service.login.RedisService;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
Expand All @@ -17,15 +20,27 @@
public class CustomSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
private final JWTUtil jwtUtil;

private final Long refreshTokenValidTime = (60 * 1000L) * 60 * 24 * 7; // 7일

@Value("${google.callback-uri}")
private String callbackUri;
// https://stuffinout.site/oauth-callback?token=&memberId=
private final RedisService redisService;

@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
// OAuth2User
CustomOauth2User customUserDetails = (CustomOauth2User) authentication.getPrincipal();
TokenInfo token = jwtUtil.generateToken(customUserDetails.getMemberId());
TokenInfo tokenInfo = jwtUtil.generateToken(customUserDetails.getMemberId());

redisService.setValues(tokenInfo.getRefreshToken(), customUserDetails.getMemberId());

response.addHeader("Authorization", tokenInfo.getGrantType() + " " + tokenInfo.getAccessToken());
response.setHeader(HttpHeaders.SET_COOKIE, "refreshToken=" + tokenInfo.getRefreshToken() + "; Path=/; HttpOnly; Secure; Max-Age=" + refreshTokenValidTime + "; SameSite=None");

response.sendRedirect(callbackUri + token.getAccessToken());
response.sendRedirect(callbackUri + tokenInfo.getAccessToken() +
"&memberId=" + customUserDetails.getMemberId() +
"&isActive=" + customUserDetails.getIsActive() +
"&imageId=" + customUserDetails.getImageId());
}
}
Loading
Loading