Skip to content

Commit

Permalink
Feat: Google, Naver 로그인 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
goalSetter09 committed Jul 14, 2024
1 parent ce6dc77 commit 3a0147d
Show file tree
Hide file tree
Showing 15 changed files with 99 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,38 +40,38 @@ public ResponseEntity<Void> joinProcess(@RequestBody JoinRequest joinRequest) {
}


@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest, HttpServletResponse response) {
Member member = memberRepository.findByUsername(loginRequest.getUsername());

if (member == null || !member.getEmail().equals(loginRequest.getEmail())) {
return ResponseEntity.status(401).build();
}

String username = member.getUsername();
String role = member.getRole();
System.out.println("role = " + role);

//토큰 생성
String access = jwtUtil.createJwt("access", username, role, 600000L);
String refresh = jwtUtil.createJwt("refresh", username, role, 86400000L);

addRefreshEntity(username, refresh, 86400000L);

//응답 설정
response.setHeader("access", access);
response.setHeader("refresh", refresh);
response.setStatus(HttpStatus.OK.value());
// LoginResponse loginResponse = new LoginResponse(access, refresh);
return ResponseEntity.ok("Login Success");
}

private void addRefreshEntity(String username, String refresh, Long expiredMs) {
// @PostMapping("/login")
// public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest, HttpServletResponse response) {
// Member member = memberRepository.findByUsername(loginRequest.getUsername());
//
// if (member == null || !member.getEmail().equals(loginRequest.getEmail())) {
// return ResponseEntity.status(401).build();
// }
//
// String memberId = member.getMemberId();
// String role = member.getRoleKey();
// System.out.println("role = " + role);
//
// //토큰 생성
// String access = jwtUtil.createJwt("access", memberId, role, 600000L);
// String refresh = jwtUtil.createJwt("refresh", memberId, role, 86400000L);
//
// addRefreshEntity(memberId, refresh, 86400000L);
//
// //응답 설정
// response.setHeader("access", access);
// response.setHeader("refresh", refresh);
// response.setStatus(HttpStatus.OK.value());
//// LoginResponse loginResponse = new LoginResponse(access, refresh);
// return ResponseEntity.ok("Login Success");
// }

private void addRefreshEntity(String memberId, String refresh, Long expiredMs) {

Date date = new Date(System.currentTimeMillis() + expiredMs);

RefreshEntity refreshEntity = new RefreshEntity();
refreshEntity.setUsername(username);
refreshEntity.setMemberId(memberId);
refreshEntity.setRefresh(refresh);
refreshEntity.setExpiration(date.toString());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public Collection<? extends GrantedAuthority> getAuthorities() {
@Override
public String getAuthority() {

return member.getRole();
return member.getRoleKey();
}
});

Expand All @@ -34,7 +34,7 @@ public String getAuthority() {
@Override
public String getPassword() {

return member.getPassword();
return null;
}

@Override
Expand Down
21 changes: 13 additions & 8 deletions src/main/java/com/cotato/squadus/common/config/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
import com.cotato.squadus.common.config.filter.CustomLogoutFilter;
import com.cotato.squadus.common.config.filter.JWTFilter;
import com.cotato.squadus.common.config.jwt.JWTUtil;
import com.cotato.squadus.common.oauth2.CustomOAuth2UserService;
import com.cotato.squadus.common.oauth2.CustomSuccessHandler;
import com.cotato.squadus.domain.auth.enums.MemberRole;
import com.cotato.squadus.domain.auth.repository.RefreshRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.CachingUserDetailsService;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
Expand All @@ -27,6 +30,7 @@ public class SecurityConfig {
"/v1/api/auth/**",
"/",
"/reissue",
"/favicon.ico"
};

private final AuthenticationConfiguration authenticationConfiguration;
Expand All @@ -35,6 +39,8 @@ public class SecurityConfig {

private final RefreshRepository refreshRepository;

private final CustomOAuth2UserService customOAuth2UserService;
private final CustomSuccessHandler customSuccessHandler;
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {

Expand Down Expand Up @@ -75,15 +81,14 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// //JWTFilter 등록
http
.addFilterBefore(new JWTFilter(jwtUtil), UsernamePasswordAuthenticationFilter.class);
http
.addFilterBefore(new CustomLogoutFilter(jwtUtil, refreshRepository), LogoutFilter.class);
//
// //필터 추가 LoginFilter()는 인자를 받음 (AuthenticationManager() 메소드에 authenticationConfiguration 객체를 넣어야 함) 따라서 등록 필요
// //AuthenticationManager()와 JWTUtil 인수 전달
// http
// .addFilterAt(new LoginFilter(authenticationManager(authenticationConfiguration), jwtUtil, refreshRepository), UsernamePasswordAuthenticationFilter.class);

//세션 설정
// .addFilterBefore(new CustomLogoutFilter(jwtUtil, refreshRepository), LogoutFilter.class);
http
.oauth2Login((oauth2) -> oauth2
.userInfoEndpoint((userInfoEndpointConfig) -> userInfoEndpointConfig
.userService(customOAuth2UserService))
.successHandler(customSuccessHandler)
);
http
.sessionManagement((session) -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
import com.cotato.squadus.common.config.jwt.JWTUtil;
import com.cotato.squadus.api.auth.dto.CustomUserDetails;
import com.cotato.squadus.domain.auth.entity.Member;
import com.cotato.squadus.domain.auth.enums.MemberRole;
import io.jsonwebtoken.ExpiredJwtException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
Expand All @@ -16,6 +18,7 @@
import java.io.IOException;
import java.io.PrintWriter;

@Slf4j
public class JWTFilter extends OncePerRequestFilter {

private final JWTUtil jwtUtil;
Expand All @@ -31,9 +34,10 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
// 헤더에서 access키에 담긴 토큰을 꺼냄
String accessToken = request.getHeader("access");


// 토큰이 없다면 다음 필터로 넘김
if (accessToken == null) {
System.out.println("accessToken is null");
log.info("Access token is null");
filterChain.doFilter(request, response);

return;
Expand Down Expand Up @@ -71,10 +75,14 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
String username = jwtUtil.getUsername(accessToken);
String role = jwtUtil.getRole(accessToken);

Member member = new Member();
member.setUsername(username);
member.setRole(role);
log.info("username : {} role : {}", username, role);

Member member = Member.builder()
.username(username)
.memberRole(MemberRole.MEMBER)
.build();
CustomUserDetails customUserDetails = new CustomUserDetails(member);
log.info("customUserDetails : {}", customUserDetails);

Authentication authToken = new UsernamePasswordAuthenticationToken(customUserDetails, null, customUserDetails.getAuthorities());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ protected void successfulAuthentication(HttpServletRequest request, HttpServletR
response.setStatus(HttpStatus.OK.value());
}

private void addRefreshEntity(String username, String refresh, Long expiredMs) {
private void addRefreshEntity(String memberId, String refresh, Long expiredMs) {

Date date = new Date(System.currentTimeMillis() + expiredMs);

RefreshEntity refreshEntity = new RefreshEntity();
refreshEntity.setUsername(username);
refreshEntity.setMemberId(memberId);
refreshEntity.setRefresh(refresh);
refreshEntity.setExpiration(date.toString());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,17 @@ public Boolean isExpired(String token) {
return Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token).getPayload().getExpiration().before(new Date());
}

public String createJwt(String category, String username, String role, Long expiredMs) {
public String createJwt(String category, String memberId, String role, Long expiredMs) {

return Jwts.builder()
.claim("category", category)
.claim("username", username)
.claim("memberId", memberId)
.claim("role", role)
.issuedAt(new Date(System.currentTimeMillis()))
.expiration(new Date(System.currentTimeMillis() + expiredMs))
.signWith(secretKey)
.compact();


}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ public class RefreshEntity {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String memberId;
private String username;
private String refresh;
private String expiration;
}
15 changes: 8 additions & 7 deletions src/main/java/com/cotato/squadus/common/dto/LoginDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,20 @@

@Getter
public class LoginDto {
private String uniqueId;
private String username;
private String memberId;
private String name;
private String role;

public LoginDto(Member member){
this.uniqueId = member.getMemberId();
this.username = member.getUsername();
this.role = member.getMemberRole().getKey();
this.memberId = member.getMemberId();
this.name = member.getUsername();
this.role = member.getRoleKey();
}

@Builder
public LoginDto(String uniqueId, String role){
this.uniqueId = uniqueId;
public LoginDto(String memberId, String name, String role){
this.memberId = getMemberId();
this.name = getName();
this.role = role;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
import com.cotato.squadus.domain.auth.enums.MemberRole;
import lombok.Builder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

@Getter
@Builder
@Slf4j
public class OAuth2Attribute {

private Map<String, Object> attributes;
Expand All @@ -24,6 +26,7 @@ public static OAuth2Attribute of(String registrationId, Map<String, Object> attr
return ofNaver(attributes);
}


private static OAuth2Attribute ofGoogle(Map<String, Object> attributes) {
return OAuth2Attribute.builder()
.name(attributes.get("name").toString())
Expand All @@ -35,6 +38,7 @@ private static OAuth2Attribute ofGoogle(Map<String, Object> attributes) {

private static OAuth2Attribute ofNaver(Map<String, Object> attributes) {
Map<String, Object> attributesMap = (Map<String, Object>) attributes.get("response");
log.info(attributesMap.toString());

return OAuth2Attribute.builder()
.name(attributesMap.get("name").toString())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ public Map<String, Object> getAttributes() {
return null;
}

public String getUniqueId(){
return loginDto.getUniqueId();
public String getMemberId(){
return loginDto.getMemberId();
}

@Override
public String getName() {
return loginDto.getUsername();
return loginDto.getName();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.cotato.squadus.domain.auth.entity.Member;
import com.cotato.squadus.domain.auth.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
Expand All @@ -13,6 +14,7 @@

@RequiredArgsConstructor
@Service
@Slf4j
public class CustomOAuth2UserService extends DefaultOAuth2UserService {

private final MemberRepository memberRepository;
Expand All @@ -30,13 +32,16 @@ public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2Authentic
Member member = saveOrUpdate(attribute, uniqueId);
LoginDto loginDto = new LoginDto(member);

log.info("CustomOAuth2UserService loadUser: {}", loginDto);
return new CustomOAuth2User(loginDto);
}

private Member saveOrUpdate(OAuth2Attribute attribute, String memberId){
Member member = memberRepository.findByMemberId(memberId)
.map(entity -> entity.update(attribute.getEmail(), attribute.getName()))
.orElse(attribute.toEntity(memberId));

log.info("CustomOAuth2UserService saveOrUpdate: {}", member);
return memberRepository.save(member);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
Expand All @@ -18,12 +19,14 @@
import java.util.Iterator;

@Component
@Slf4j
public class CustomSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

private final JWTUtil jwtUtil;
private final RefreshRepository refreshRepository;

public CustomSuccessHandler(JWTUtil jwtUtil, RefreshRepository refreshRepository) {
log.info("CustomSuccessHandler instantiated");
this.jwtUtil = jwtUtil;
this.refreshRepository = refreshRepository;
}
Expand All @@ -35,20 +38,20 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo
//OAuth2User
CustomOAuth2User customUserDetails = (CustomOAuth2User) authentication.getPrincipal();

String uniqueId = customUserDetails.getUniqueId();
String memberId = customUserDetails.getMemberId();
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
Iterator<? extends GrantedAuthority> iterator = authorities.iterator();
GrantedAuthority auth = iterator.next();
String role = auth.getAuthority();

String access = jwtUtil.createJwt("access", uniqueId, role, 600000L);
String refresh = jwtUtil.createJwt("refresh", uniqueId, role, 86400000L);
String access = jwtUtil.createJwt("access", memberId, role, 600000L);
String refresh = jwtUtil.createJwt("refresh", memberId, role, 86400000L);

addRefreshEntity(uniqueId, refresh, 86400000L);
addRefreshEntity(memberId, refresh, 86400000L);

response.setHeader("access", access);
response.addCookie(createCookie("refresh", refresh));
response.sendRedirect("http://localhost:3000/");
response.sendRedirect("http://localhost:8080/");
}

private void addRefreshEntity(String memberId, String refresh, Long expiredMs) {
Expand Down
Loading

0 comments on commit 3a0147d

Please sign in to comment.