forked from KakaoTech-BootCamp-Team-2/Kaboo-Auth
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- 권한 필요한 API 접속 시 카카오 로그인 페이지 반환 - 로그인 성공 시 가입이 안되어있으면 가입, 되어있으면 권한 부여 - 권한은 JWT 발급 후 쿠키에 추가, 매 요청마다 JwtFilter를 거치며 쿠키의 Jwt 확 Related to: KakaoTech-BootCamp-Team-2#1
- Loading branch information
1 parent
0f1e1eb
commit 51acd08
Showing
21 changed files
with
626 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
src/main/java/kaboo/kaboo_auth/config/PasswordEncoderConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package kaboo.kaboo_auth.config; | ||
|
||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | ||
import org.springframework.security.crypto.password.PasswordEncoder; | ||
|
||
@Configuration | ||
public class PasswordEncoderConfig { | ||
@Bean | ||
public PasswordEncoder passwordEncoder() { | ||
return new BCryptPasswordEncoder(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package kaboo.kaboo_auth.config; | ||
|
||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; | ||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; | ||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; | ||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; | ||
import org.springframework.security.config.http.SessionCreationPolicy; | ||
import org.springframework.security.web.SecurityFilterChain; | ||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | ||
|
||
import kaboo.kaboo_auth.domain.handler.LoginSuccessHandler; | ||
import kaboo.kaboo_auth.domain.jwt.filter.JwtFilter; | ||
import kaboo.kaboo_auth.service.CustomOAuth2Service; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@Configuration | ||
@EnableWebSecurity | ||
@RequiredArgsConstructor | ||
public class SecurityConfig { | ||
|
||
private final JwtFilter jwtFilter; | ||
private final CustomOAuth2Service customOAuth2Service; | ||
private final LoginSuccessHandler loginSuccessHandler; | ||
|
||
@Bean | ||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { | ||
http | ||
.authorizeHttpRequests(auth -> auth | ||
.requestMatchers("/").permitAll() | ||
.anyRequest().authenticated()) // 그 외 요청은 인증 필요 | ||
.headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin)); | ||
|
||
http | ||
.csrf(AbstractHttpConfigurer::disable) | ||
.formLogin(AbstractHttpConfigurer::disable) | ||
.httpBasic(AbstractHttpConfigurer::disable) | ||
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class) | ||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); | ||
|
||
http.oauth2Login(auth -> auth | ||
.userInfoEndpoint(userInfoEndpointConfig -> userInfoEndpointConfig.userService(customOAuth2Service)) | ||
.successHandler(loginSuccessHandler)); | ||
|
||
return http.build(); | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
src/main/java/kaboo/kaboo_auth/controller/MainController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package kaboo.kaboo_auth.controller; | ||
|
||
import org.springframework.security.core.Authentication; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
public class MainController { | ||
|
||
@GetMapping("/") | ||
public String mainAPI() { | ||
return "누구나 접근가능한 API입니다."; | ||
} | ||
|
||
@GetMapping("/test") | ||
public String authAPI() { | ||
return "권한 Test API 입니다."; | ||
} | ||
|
||
@GetMapping("/auth/hello") | ||
public String helloAuth(Authentication authentication) { | ||
return "인가 받은 사용자 " + authentication.getName() + " 님 환영합니다."; | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
src/main/java/kaboo/kaboo_auth/domain/CustomUserDetails.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package kaboo.kaboo_auth.domain; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
import java.util.Map; | ||
|
||
import org.springframework.security.core.GrantedAuthority; | ||
import org.springframework.security.core.userdetails.UserDetails; | ||
import org.springframework.security.oauth2.core.user.OAuth2User; | ||
|
||
import kaboo.kaboo_auth.domain.entity.Member; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@RequiredArgsConstructor | ||
public class CustomUserDetails implements OAuth2User, UserDetails { | ||
private final Member member; | ||
|
||
@Override | ||
public String getUsername() { | ||
return member.getUsername(); | ||
} | ||
|
||
@Override | ||
public String getName() { | ||
return member.getNickname(); | ||
} | ||
|
||
@Override | ||
public String getPassword() { | ||
return member.getPassword(); | ||
} | ||
|
||
@Override | ||
public Map<String, Object> getAttributes() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public Collection<? extends GrantedAuthority> getAuthorities() { | ||
Collection<GrantedAuthority> collection = new ArrayList<>(); | ||
collection.add((GrantedAuthority)() -> member.getRole().toString()); | ||
|
||
return collection; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package kaboo.kaboo_auth.domain; | ||
|
||
import lombok.Getter; | ||
|
||
@Getter | ||
public enum UserRole { | ||
ROLE_ADMIN("ROLE_ADMIN"), | ||
ROLE_USER("ROLE_USER"); | ||
|
||
private final String role; | ||
|
||
UserRole(String role) { | ||
this.role = role; | ||
} | ||
} |
72 changes: 72 additions & 0 deletions
72
src/main/java/kaboo/kaboo_auth/domain/dto/response/KakaoResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package kaboo.kaboo_auth.domain.dto.response; | ||
|
||
import java.util.Map; | ||
|
||
/** Kakao Response 형태 | ||
* { | ||
* id: int, | ||
* connected_at: Date | ||
* properties: { | ||
* nickname: String | ||
* profile_image: URL | ||
* thumbnail_image: URL | ||
* }, | ||
* kakao_account: { | ||
* profile_nickname_needs_agreement: boolean, | ||
* profile_image_needs_agreement: boolean | ||
* profile: { | ||
* nickname: String | ||
* thumbnail_image_url: URL | ||
* profile_image_url: URL | ||
* is_default_image: boolean | ||
* is_default_nickname: boolean | ||
* }, | ||
* has_email=true, | ||
* email_needs_agreement=false, | ||
* is_email_valid=true, | ||
* is_email_verified=true, | ||
* [email protected] | ||
* } | ||
* | ||
* } | ||
*/ | ||
|
||
public class KakaoResponse implements OAuth2Response { | ||
private final Map<String, Object> attribute; | ||
|
||
public KakaoResponse(Map<String, Object> attribute) { | ||
this.attribute = attribute; | ||
} | ||
|
||
@Override | ||
public String getProvider() { | ||
return "kakao"; | ||
} | ||
|
||
@Override | ||
public String getProviderId() { | ||
return attribute.get("id").toString(); | ||
} | ||
|
||
@Override | ||
public String getEmail() { | ||
Map<String, Object> kakaoAccount = (Map<String, Object>)attribute.get("kakao_account"); | ||
|
||
// "kakao_account" 맵에서 "email" 키의 값을 가져옴 | ||
if (kakaoAccount != null && kakaoAccount.containsKey("email")) { | ||
return kakaoAccount.get("email").toString(); | ||
} | ||
return null; // email이 없을 경우 | ||
} | ||
|
||
@Override | ||
public String getNickname() { | ||
Map<String, Object> properties = (Map<String, Object>)attribute.get("properties"); | ||
|
||
// "properties" 맵에서 "nickname" 키의 값을 가져옴 | ||
if (properties != null && properties.containsKey("nickname")) { | ||
return properties.get("nickname").toString(); | ||
} | ||
return null; // nickname이 없을 경우 | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
src/main/java/kaboo/kaboo_auth/domain/dto/response/OAuth2Response.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package kaboo.kaboo_auth.domain.dto.response; | ||
|
||
public interface OAuth2Response { | ||
String getProvider(); | ||
|
||
String getProviderId(); | ||
|
||
String getEmail(); | ||
|
||
String getNickname(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
src/main/java/kaboo/kaboo_auth/domain/handler/LoginSuccessHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package kaboo.kaboo_auth.domain.handler; | ||
|
||
import java.io.IOException; | ||
|
||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; | ||
import org.springframework.stereotype.Component; | ||
|
||
import jakarta.servlet.http.Cookie; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import kaboo.kaboo_auth.domain.jwt.JwtTokenProvider; | ||
import kaboo.kaboo_auth.domain.jwt.entity.JwtAccessToken; | ||
import kaboo.kaboo_auth.domain.jwt.entity.JwtRefreshToken; | ||
import kaboo.kaboo_auth.domain.jwt.repository.JwtAccessTokenRepository; | ||
import kaboo.kaboo_auth.domain.jwt.repository.JwtRefreshTokenRepository; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
public class LoginSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { | ||
|
||
private final JwtAccessTokenRepository jwtAccessTokenRepository; | ||
private final JwtRefreshTokenRepository jwtRefreshTokenRepository; | ||
private final JwtTokenProvider jwtTokenProvider; | ||
private final int accessTokenValidTime = 10 * 60; // 유효기간 : 10분 | ||
private final int refreshTokenValidTime = 10 * 24 * 60 * 60; // 유효기간 : 10일 | ||
|
||
private Cookie createCookie(String key, String value, int maxAge) { | ||
Cookie cookie = new Cookie(key, value); | ||
cookie.setMaxAge(maxAge); | ||
cookie.setPath("/"); | ||
cookie.setHttpOnly(true); | ||
|
||
return cookie; | ||
} | ||
|
||
@Override | ||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, | ||
Authentication authentication) throws | ||
IOException { | ||
String username = authentication.getName(); | ||
String accessToken = jwtTokenProvider.createAccessToken(username); | ||
String refreshToken = jwtTokenProvider.createRefreshToken(username); | ||
|
||
jwtAccessTokenRepository.save(new JwtAccessToken(username, accessToken)); | ||
jwtRefreshTokenRepository.save(new JwtRefreshToken(username, refreshToken)); | ||
|
||
response.addCookie(createCookie("Username", username, refreshTokenValidTime)); | ||
response.addCookie(createCookie("Authorization", accessToken, accessTokenValidTime)); | ||
response.addCookie(createCookie("RefreshToken", refreshToken, refreshTokenValidTime)); | ||
response.sendRedirect("/"); | ||
} | ||
} |
Oops, something went wrong.