โ Git
https://github.com/ellaCoo/sns/pull/46
๐ ์ํฉ
์ด์ ์ SpringSecurity๋ก ๋ก๊ทธ์ธ ๊ธฐ๋ฅ(https://github.com/ellaCoo/sns/pull/27)์ ๊ตฌํํ๋๋ฐ,
ํ์๊ฐ์ ๊ธฐ๋ฅ๋ง๊ณ ์นด์นด์ค ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ ค๊ณ ํ๋ค.


1. build.gradle ์ Spring Security OAuth2 Client ์์กด์ฑ ์ถ๊ฐํ๋ค
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' // kakao auth
2. application.yaml ํ์ผ์ ์นด์นด์ค OAuth2 ์คํ๋ง ํ๋กํผํฐ ์ค์ ์ ์ถ๊ฐํ๋ค
์นด์นด์ค ๊ฐ๋ฐ์ ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์ฌ OAuth 2.0 ์๋น์ค๋ฅผ ์ฌ์ฉํ๋๋ฐ ํ์ํ ์ ๋ณด๋ฅผ ์ ๋ฆฌํจ
์ฌ๊ธฐ์ client-id, client-secret์ ๋น๋ฐ์ ๋ณด์ด๋ฏ๋ก ์ค์ ๊ฐ์ ๋ฃ์ง ์๊ณ , ๋์ค์ ์ธ๋ถ ํ๊ฒฝ๋ณ์๋ก ๋ฃ์ ์ ์๋๋ก ํจ
security:
oauth2:
client:
registration:
kakao:
client-id: ${KAKAO_OAUTH_CLIENT_ID}
client-secret: ${KAKAO_OAUTH_CLIENT_SECRET}
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/login/oauth2/code/kakao"
client-authentication-method: POST
provider:
kakao:
authorization-uri: <https://kauth.kakao.com/oauth/authorize>
token-uri: <https://kauth.kakao.com/oauth/token>
user-info-uri: <https://kapi.kakao.com/v2/user/me>
user-name-attribute: id
3. https://developers.kakao.com/
- ๋ก๊ทธ์ธ ํ ์ ํ๋ฆฌ์ผ์ด์ ์๋ก ์์ฑ- ์ฑ ์ค์ > ํ๋ซํผ > Web (ํ์ฌ ๋ก์ปฌ์์ ์งํํ๊ณ ์์ผ๋ฏ๋ก http://localhost:8080 ๋ง ์ถ๊ฐ)
- ์ ํ ์ค์ > ์นด์นด์ค ๋ก๊ทธ์ธ > Redirect URI
- ์ ํ ์ค์ > ๋์ํญ๋ชฉ > ๋๋ค์ ์ค์
- ์ ํ ์ค์ > ๋ณด์ > Client Secret ์ฝ๋ ๋ฐ๊ธ
⇒ application.yaml ์ client-secret: ${KAKAO_OAUTH_CLIENT_SECRET}
- ์ฑ ์ค์ > ์ฑ ํค > REST API ํค
⇒ application.yaml ์ client-id: ${KAKAO_OAUTH_CLIENT_ID}


4. ์ธ์ฆ ์ ๋ณด๋ฅผ ๋ค๋ฃจ๋ SnsPrincipal ์ OAuth ์ธ์ฆ ์ ๋ณด๋ฅผ ๋ค๋ฃฐ ์ ์๋๋ก ๊ธฐ๋ฅ ์ถ๊ฐ
OAuth2User ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํด์ Spring OAuth Client ๋ ๊ธฐ์กด๊ณผ ๋์ผํ๊ฒ ์ธ์ฆ ์ ๋ณด๋ฅผ ์ธ์ํ ์ ์๊ฒ๋ ํจ
public record SnsPrincipal(
String username,
String password,
Collection<? extends GrantedAuthority> authorities,
String email,
String nickname,
String memo,
Map<String, Object> oAuth2Attributes
) implements UserDetails, OAuth2User {
**@Override
public Map<String, Object> getAttributes() {
return oAuth2Attributes;
}
@Override
public String getName() {
return username;
}**
5. ์นด์นด์ค OAuth2 ์ธ์ฆ ํ ๋ฐํ๋ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์ฒ๋ฆฌ - KakaoOAuth2Response
record KakaoOAuth2Response
- record : ๋ถ๋ณ์ฑ(immutable)์ ๋ณด์ฅ, ๋ชจ๋ ํ๋๋ฅผ ์๋์ผ๋ก ์์ฑ์์ ๋ฃ์ด์ค
- ์นด์นด์ค์์ ๋ฐํ๋ OAuth2 ์๋ต ๋ฐ์ดํฐ๋ฅผ ๋ด๋ DTO
- id (์นด์นด์ค ์ฌ์ฉ์ ID), connectedAt(์นด์นด์ค ์๋น์ค์ ์ฐ๊ฒฐ๋ ์์ ), properties(๊ธฐํ ์์ฑ), kakaoAccount(์นด์นด์ค ๊ณ์ ์ ๋ณด)
record KakaoAccount
- KakaoOAuth2Response ๋ด๋ถ์ ์ ์๋ ํด๋์ค
- ์นด์นด์ค ๊ณ์ ์ ๋ณด์ ๋ํ ์ธ๋ถ ์ ๋ณด + ์ด๋ฉ์ผ๊ณผ ํ๋กํ ์ ๋ณด์ ๋ํ ํ๋ ์ฒ๋ฆฌ
public static KakaoOAuth2Response from(Map<String, Object> attributes)
- ์นด์นด์ค OAuth2 ์๋ต์ผ๋ก๋ถํฐ KakaoOAuth2Response ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ์ ์ ํฉํ ๋ฆฌ ๋ฉ์๋
- JSON์ด๋ Map ํ์์ผ๋ก ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ํ์ฑํด ๊ฐ ํ๋์ ๋ง๊ฒ ๋งคํ
public String email()
- ์นด์นด์ค ๊ณ์ ์ ๋ณด์์ ์ด๋ฉ์ผ์ ๋ฐํ
public String nickname()
- ์นด์นด์ค ๊ณ์ ์ ๋ณด์์ ๋๋ค์์ ๋ฐํ
public record KakaoOAuth2Response(
Long id,
LocalDateTime connectedAt,
Map<String, Object> properties,
KakaoAccount kakaoAccount
) {
public record KakaoAccount(
Boolean profileNicknameNeedsAgreement,
Profile profile,
Boolean hasEmail,
Boolean emailNeedsAgreement,
Boolean isEmailValid,
Boolean isEmailVerified,
String email
) {
public record Profile(String nickname) {
public static Profile from(Map<String, Object> attributes) {
return new Profile(String.valueOf(attributes.get("nickname")));
}
}
public static KakaoAccount from(Map<String, Object> attributes) {
return new KakaoAccount(
Boolean.valueOf(String.valueOf(attributes.get("profile_nickname_needs_agreement"))),
Profile.from((Map<String, Object>) attributes.get("profile")),
Boolean.valueOf(String.valueOf(attributes.get("has_email"))),
Boolean.valueOf(String.valueOf(attributes.get("email_needs_agreement"))),
Boolean.valueOf(String.valueOf(attributes.get("is_email_valid"))),
Boolean.valueOf(String.valueOf(attributes.get("is_email_verified"))),
String.valueOf(attributes.get("email"))
);
}
public String nickname() { return this.profile().nickname(); }
}
public static KakaoOAuth2Response from(Map<String, Object> attributes) {
return new KakaoOAuth2Response(
Long.valueOf(String.valueOf(attributes.get("id"))),
LocalDateTime.parse(
String.valueOf(attributes.get("connected_at")),
DateTimeFormatter.ISO_INSTANT.withZone(ZoneId.systemDefault())
),
(Map<String, Object>) attributes.get("properties"),
KakaoAccount.from((Map<String, Object>) attributes.get("kakao_account"))
);
}
public String email() { return this.kakaoAccount().email(); }
public String nickname() { return this.kakaoAccount().nickname(); }
}
6. SecurityConfig ํด๋์ค ์ค์ - Spring Security์ ์นด์นด์ค OAuth2 ์ธ์ฆ์ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์ ์ธ์ฆ ๋ฐ ๊ถํ ๋ถ์ฌ๋ฅผ ์ฒ๋ฆฌ
Spring Security ๋ ์ธ์ฆ,์ธ๊ฐ์ ๋ํ ์ฒ๋ฆฌ๋ฅผ ์ฌ๋ฌ๊ฐ์ ํํฐ๋ฅผ ํตํด ์ฐ์์ ์ผ๋ก ์คํํ๋ค.
Security Filter Chain ๋น์ ์์ฑํ๋ securityFilterChain ๋ฉ์๋๊ฐ Security Filter Chain ์ ๋ํ ์ ๋ฐ์ ์ธ ์ค์ ์ ๊ตฌ์ฑํ๋ฉฐ
ํด๋น ๋ฉ์๋์ ๋งค๊ฐ๋ณ์์ธ HttpSecurity ๊ฐ ์ค์ ์ ๊ธฐ๋ฐ์ผ๋ก Security Filter Chain ์ ์์ฑํ๋ค.
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(
HttpSecurity http,
OAuth2UserService<OAuth2UserRequest, OAuth2User> oAuth2UserService
) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.requestMatchers("/api/**").permitAll()
.requestMatchers(
HttpMethod.GET,
"/",
"/posts",
"/posts/hashtag"
).permitAll()
.requestMatchers(
HttpMethod.POST,
"/posts"
).permitAll()
.anyRequest().authenticated()
)
.formLogin(withDefaults())
.logout(logout -> logout.logoutSuccessUrl("/"))
.oauth2Login(oAuth -> oAuth
.userInfoEndpoint(userInfo -> userInfo
.userService(oAuth2UserService)
)
)
.csrf(csrf -> csrf.ignoringRequestMatchers("/api/**"))
.build();
}
@Bean
public UserDetailsService userDetailsService(UserAccountService userAccountService) {
return username -> userAccountService
.searchUser(username)
.map(SnsPrincipal::fromDto)
.orElseThrow(() -> new UsernameNotFoundException("์ ์ ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค - username: " + username));
}
@Bean
public OAuth2UserService<OAuth2UserRequest, OAuth2User> oAuth2UserService(
UserAccountService userAccountService,
PasswordEncoder passwordEncoder
) {
final DefaultOAuth2UserService delegate = new DefaultOAuth2UserService();
return userRequest -> {
OAuth2User oAuth2User = delegate.loadUser(userRequest);
KakaoOAuth2Response kakaoResponse = KakaoOAuth2Response.from(oAuth2User.getAttributes());
String registrationId = userRequest.getClientRegistration().getRegistrationId();
String providerId = String.valueOf(kakaoResponse.id());
String username = registrationId + "_" + providerId;
String dummyPassword = passwordEncoder.encode("{bcrypt}" + UUID.randomUUID());
return userAccountService.searchUser(username)
.map(SnsPrincipal::fromDto)
.orElseGet(() ->
SnsPrincipal.fromDto(
userAccountService.saveUser(
username,
dummyPassword,
kakaoResponse.email(),
kakaoResponse.nickname(),
null
)
)
);
};
}
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
}
6-1. securityFilterChain ๋ฉ์๋
HTTP ์์ฒญ์ ๋ํ ๋ณด์ ํํฐ ์ฒด์ธ์ ์ค์
- ๋ชจ๋ ์์ฒญ์ด Spring Security์ ํํฐ๋ฅผ ๊ฑฐ์น๊ธฐ ๋๋ฌธ์, ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ค์ด์ค๋ ๋ชจ๋ ์์ฒญ์ ๋ํด ๋ณด์ ์ค์ ์ ์ ์ฉ
Spring Security์ ๋ณด์ ๊ตฌ์ฑ์ ๋ด๋นํ๋ฉฐ, ์ฌ๋ฌ ํํฐ๋ฅผ ์ค์ ํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ธ์ฆ๊ณผ ์ธ๊ฐ๋ฅผ ์ ์ดํจ
authorizeHttpRequests
: HTTP ์์ฒญ์ ๋ํด ์ด๋ค ์์ฒญ์ ํ์ฉํ๊ณ ์ด๋ค ์์ฒญ์ ์ธ์ฆํด์ผ ํ๋์ง ์ ์
- PathRequest.toStaticResources().atCommonLocations().permitAll()
: ์ ์ ๋ฆฌ์์ค(CSS, JS ๋ฑ)์ ๋ํ ์ ๊ทผ์ ๋ชจ๋ ํ์ฉ
- GET /, /posts, /posts/hashtag: ์ด GET ์์ฒญ๋ค ๋ชจ๋ ํ์ฉ
- POST /posts: POST ์์ฒญ๋ ์ธ์ฆ ์์ด ํ์ฉ
- anyRequest().authenticated(): ๊ทธ ์ธ ๋ชจ๋ ์์ฒญ์ ์ธ์ฆ ํ์
formLogin(withDefaults())
: ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณต๋๋ ๋ก๊ทธ์ธ ํผ์ ์ฌ์ฉํ๊ฒ ๋ค๋ ์ค์
logout(logout -> logout.logoutSuccessUrl("/"))
: ๋ก๊ทธ์์ ํ์ ๋ฃจํธ ํ์ด์ง("/")๋ก ๋ฆฌ๋ค์ด๋ ํธ
oauth2Login
: OAuth2๋ฅผ ์ฌ์ฉํ์ฌ ๋ก๊ทธ์ธํ ์ ์๋๋ก ์ค์ ํฉ๋๋ค. userService(oAuth2UserService)๋ฅผ ํตํด ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์ฒ๋ฆฌํ๋ OAuth2UserService๋ฅผ ์ง์
csrf(csrf -> csrf.ignoringRequestMatchers("/api/**"))
: CSRF ๋ณดํธ๋ /api/** ๊ฒฝ๋ก์์๋ ๋นํ์ฑํ
6-2. userDetailsService ๋ฉ์๋
์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ๋ก์ง์ ์ ์
- ํผ ๋ก๊ทธ์ธ์ ํตํด ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ์ ์๋ํ ๋ ํธ์ถ๋จ
UserDetailsService๋ Spring Security์์ ์ธ์ฆ ์ ๋ณด๋ฅผ ์กฐํํ ๋ ์ฌ์ฉ๋จ
username์ ๋ฐ์์ UserAccountService๋ฅผ ํตํด ์ฌ์ฉ์๋ฅผ ์กฐํํ๋ค
6-3. oAuth2UserService ๋ฉ์๋
OAuth2 ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์ฒ๋ฆฌํ๋ ์๋น์ค ๊ฐ์ฒด๋ฅผ ์์ฑ
(์ฌ๊ธฐ์์ ์นด์นด์ค OAuth2 ๋ก๊ทธ์ธ์ ์ฒ๋ฆฌํ๋ ๋ฐฉ์ ์ ์)
์ฌ์ฉ์๊ฐ ์นด์นด์ค ํตํด ์ธ์ฆ ์๋ฃ
→ ์นด์นด์ค ์๋ฒ๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์ ๋ฌํ๋ฉด ์ด ๋ OAuth2UserRequest ๊ฐ์ฒด๊ฐ ์์ฑ๋๊ณ , oAuth2UserService ๋ฉ์๋๊ฐ ํธ์ถ๋จ
์ด ๋ฉ์๋๊ฐ ๋ฐํํ OAuth2User ๊ฐ์ฒด๊ฐ Spring Security์ ์ธ์ฆ ์ ๋ณด๋ก ์ฌ์ฉ๋จ
DefaultOAuth2UserService delegate = new DefaultOAuth2UserService();
: ๊ธฐ๋ณธ OAuth2 ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๋ก๋ํ๋ ์๋น์ค๋ฅผ ์์๋ฐ๋๋ค
OAuth2User oAuth2User = delegate.loadUser(userRequest);
: OAuth2 ์์ฒญ์ ํตํด ์นด์นด์ค๋ก๋ถํฐ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์จ๋ค
KakaoOAuth2Response.from(oAuth2User.getAttributes())
: ์นด์นด์ค ์๋ต์์ ํ์ํ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์จ๋ค
- ์ฌ๊ธฐ์ ID, ์ด๋ฉ์ผ, ๋๋ค์ ๋ฑ์ ์ ๋ณด๊ฐ ์ถ์ถ๋จ
registrationId, providerId, username
: ์นด์นด์ค ์ฌ์ฉ์ ID๋ฅผ ๊ธฐ๋ฐ์ผ๋ก username์ ์์ฑ
- registrationId๋ "kakao"์ด๊ณ , providerId๋ ์นด์นด์ค์ ์ฌ์ฉ์ ID
- ๋๊ฐ ๊ฒฐํฉํ์ฌ ๊ณ ์ ํ username ์์ฑ
dummyPassword
: ์ํธํ๋ ์์ ๋น๋ฐ๋ฒํธ๋ฅผ ์์ฑ
- ์ค์ ๋ก๋ ์นด์นด์ค ๋ก๊ทธ์ธ์ ํตํด์๋ง ์ ๊ทผํ ์ ์๊ธฐ ๋๋ฌธ์ ๋น๋ฐ๋ฒํธ๋ ์ค์ํ ์์๊ฐ ์๋์ง๋ง, ์์คํ ์ ์ผ๋ก๋ ํ์ํ๋ฏ๋ก ๋๋ฏธ๊ฐ์ ์ฌ์ฉ
- ์ฌ์ฉ์๊ฐ ์ด๋ฏธ ์กด์ฌํ๋ ๊ฒฝ์ฐ, SnsPrincipal::fromDto๋ก ๋ณํํ์ฌ ๋ฐํ
- ์ฌ์ฉ์๊ฐ ์กด์ฌํ์ง ์๋ ๊ฒฝ์ฐ, ์๋ก์ด ์ฌ์ฉ์ ๊ณ์ ์ ์์ฑํ์ฌ ์ ์ฅํ ๋ค ๋ฐํ
โ ์นด์นด์ค OAuth2 ์ธ์ฆ ํ๋ฆ ๋ค์ด์ด๊ทธ๋จ
[1] ์ฌ์ฉ์ ์์ฒญ (์นด์นด์ค ๋ก๊ทธ์ธ ๋ฒํผ ํด๋ฆญ)
|
v
[2] ํด๋ผ์ด์ธํธ → ์นด์นด์ค ์๋ฒ (OAuth2 Authorization ์์ฒญ)
URL: <https://kauth.kakao.com/oauth/authorize>
- ํด๋ผ์ด์ธํธ ID, redirect URI, ์๋ต ์ ํ(authorization_code) ๋ฑ ์ ๋ฌ
|
v
[3] ์ฌ์ฉ์ → ์นด์นด์ค ์๋ฒ (์ฌ์ฉ์ ๋์ ํ๋ฉด)
- ์ฌ์ฉ์๊ฐ ์นด์นด์ค ๋์ ํ๋ฉด์์ ์ ๋ณด ์ ๊ณต์ ๋์
|
v
[4] ์นด์นด์ค ์๋ฒ → ํด๋ผ์ด์ธํธ (Authorization Code ์ ๋ฌ)
- ํด๋ผ์ด์ธํธ๋ Authorization Code๋ฅผ ๋ฐ์
- redirect URI๋ก ๋ฆฌ๋ค์ด๋ ํธ๋จ
|
v
[5] ํด๋ผ์ด์ธํธ → ์นด์นด์ค ์๋ฒ (Access Token ์์ฒญ)
URL: <https://kauth.kakao.com/oauth/token>
- Authorization Code์ ํจ๊ป ํด๋ผ์ด์ธํธ ID, ๋น๋ฐํค(client secret), redirect URI ๋ฑ ์ ๋ฌ
|
v
[6] ์นด์นด์ค ์๋ฒ → ํด๋ผ์ด์ธํธ (Access Token ์๋ต)
- Access Token์ ํฌํจํ ์ธ์ฆ ์ ๋ณด๋ฅผ ๋ฐํ
|
v
[7] ํด๋ผ์ด์ธํธ → ์นด์นด์ค API ์๋ฒ (์ฌ์ฉ์ ์ ๋ณด ์์ฒญ)
URL: <https://kapi.kakao.com/v2/user/me>
- Access Token์ ํค๋์ ํฌํจํ์ฌ ์ฌ์ฉ์ ์ ๋ณด ์์ฒญ
|
v
[8] ์นด์นด์ค ์๋ฒ → ํด๋ผ์ด์ธํธ (์ฌ์ฉ์ ์ ๋ณด ๋ฐํ)
- ์ฌ์ฉ์ ID, ์ด๋ฉ์ผ, ๋๋ค์ ๋ฑ ๋ฐํ
|
v
[9] Spring Security - `OAuth2UserService` ์คํ
- `oAuth2UserService` ๋ฉ์๋์์ ์ฌ์ฉ์ ์ ๋ณด ์ฒ๋ฆฌ
|
v
[10] ์ฌ์ฉ์ ๊ณ์ ์ฒ๋ฆฌ (DB ์กฐํ ๋ฐ ์ ์ฅ)
- ์ฌ์ฉ์๊ฐ ์กด์ฌํ๋ฉด ๋ก๊ทธ์ธ ์ฒ๋ฆฌ, ์์ผ๋ฉด ์๋ก ์์ฑ
|
v
[11] ์ธ์ฆ ์๋ฃ ํ ๋ฆฌ๋ค์ด๋ ํธ
- ์ฌ์ฉ์๊ฐ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ก๊ทธ์ธ๋ ์ํ๋ก ๋ฆฌ๋ค์ด๋ ํธ๋จ
โ ์ ๋ฆฌ
SecurityConfig ํด๋์ค์์ ๊ฐ ๋ฉ์๋๊ฐ ์ค์ ๋ก๋ Spring์ ๋น์ผ๋ก ๋ฑ๋ก๋จ
→ ๊ฐ ๊ณผ์ ์์ ๋ฉ์๋๊ฐ ์ง์ ํธ์ถ๋๋ ๊ฒ์ด ์๋๋ผ Spring์ด ๋ด๋ถ์ ์ผ๋ก ์ฒ๋ฆฌํจ
๋น์ผ๋ก ๋ฑ๋ก๋๋ค?
Spring์ ๋น์ผ๋ก ๋ฑ๋ก๋๋ค๋ ๊ฒ
= ํด๋น ๋ฉ์๋๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์์๋ ๋ Spring ์ปจํ ์คํธ์ ์ํด ์๋์ผ๋ก ์์ฑ๋๊ณ ๊ด๋ฆฌ๋๋ค
⇒ ํ ๋ฒ ์์ฑ๋ ํ Spring Security๊ฐ ์ธ์ฆ ๋ฐ ์ธ๊ฐ ๊ณผ์ ์์ ํ์ํ ๋ก์ง์ ๋น์ผ๋ก ๋ฑ๋ก๋ ๊ฐ์ฒด๋ฅผ ํตํด ์๋์ผ๋ก ์ฒ๋ฆฌํจ
์์:
securityFilterChain ๋ฉ์๋→ ์ดํ ๋ชจ๋ ์์ฒญ์ด ๋ค์ด์ฌ ๋๋ง๋ค ์ด ๋น์ด Security ํํฐ ์ฒด์ธ์ผ๋ก ๋์ํจ→ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์์ ์ ํ ๋ฒ ํธ์ถ๋๊ณ SecurityFilterChain ๋น์ ์์ฑ
๋น์ผ๋ก ๋์ํ๋ ์๋ฆฌ
1. ์ ํ๋ฆฌ์ผ์ด์ ์ด ์์๋๋ฉด
Spring์ @Configuration ์ด๋ ธํ ์ด์ ์ด ๋ถ์ ํด๋์ค๋ฅผ ์ค์บํด์
ํด๋น ํด๋์ค ์์ @Bean ์ด๋ ธํ ์ด์ ์ด ๋ถ์ ๋ฉ์๋๋ค์ ์คํ
⇒ Spring์ ๋น์ผ๋ก ๋ฑ๋ก๋ผ์ ๊ด๋ฆฌ๋จ
2. ์ฌ์ฉ์ ์์ฒญ์ด ๋ค์ด์ค๋ฉด Spring Security๋ ๋ด๋ถ์ ์ผ๋ก securityFilterChain์์ ์ค์ ๋ ํํฐ ์ฒด์ธ์ ํตํด ์์ฒญ์ ์ฒ๋ฆฌํจ
- OAuth2 ๋ก๊ทธ์ธ์ด ํ์ํ ๊ฒฝ์ฐ → OAuth2UserService ํธ์ถ
- UserDetailsService๊ฐ ํ์ํ ๊ฒฝ์ฐ → Spring Security๊ฐ ์๋์ผ๋ก ์ด๋ฅผ ์ฐธ์กฐํด ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์กฐํ
๊ฒฐ๋ก
1. ์ฌ์ฉ์๊ฐ ์นด์นด์ค ๋ก๊ทธ์ธ์ ์๋ํ ๋
- Spring Security๋ ์๋์ผ๋ก OAuth2 ์ธ์ฆ ๊ณผ์ ์ ๊ด๋ฆฌ
- ์ฌ์ฉ์๊ฐ ์ธ์ฆ์ ์๋ฃํ๋ฉด → Spring Security๋ ์๋์ผ๋ก OAuth2UserService ๋น์ ํธ์ถํด์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์ฒ๋ฆฌ
- ์ด๋ oAuth2UserService ๋น์ด ํธ์ถ๋จ → ์ฌ์ฉ์๊ฐ DB์ ์๋์ง ํ์ธํ๊ณ , ์๋ก์ด ์ฌ์ฉ์๋ฅผ ์์ฑํ๋ ๋ก์ง ์คํ
2. ํผ ๋ก๊ทธ์ธ์ ์๋ํ ๋
- ์ฌ์ฉ์๊ฐ username๊ณผ password๋ฅผ ์ ๋ ฅ
→ Spring Security๋ UserDetailsService ๋น์ ์ฌ์ฉํด์
ํด๋น username์ ๊ฐ์ง ์ฌ์ฉ์๋ฅผ ์ฐพ์
(์ด ๊ณผ์ ์์ userDetailsService ๋ฉ์๋๊ฐ ํธ์ถ๋๋ ๊ฒ ์๋๋ผ, ์ด๋ฏธ ๋ฑ๋ก๋ ๋น์ ํตํด ์ฒ๋ฆฌ๋จ)
'Back-end > Project' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [ํ๋ก์ ํธ] Redis๋ก ์บ์ฑ ๊ตฌํํ๊ธฐ (1) | 2024.09.18 |
|---|---|
| [ํ๋ก์ ํธ] N+1 ๋ฌธ์ ํด๊ฒฐํ๊ธฐ (Fetch Join+QueryDSL, Hibernate์ต์ ํ) (1) | 2024.09.12 |
| [ํ๋ก์ ํธ] JPQL โ QueryDSL ๋ก ๋ณ๊ฒฝํ๊ธฐ (0) | 2024.09.12 |
| [ํ๋ก์ ํธ] N:N ๊ด๊ณ โ 1:N & N:1 ๋ก ๊ตฌํํ๊ธฐ (1) | 2024.09.09 |
| [ํ๋ก์ ํธ] ๋๊ธ๊ณผ ๋๋๊ธ ๊ด๊ณ ๋ก์ง ์ํฐํฐ ํ๋๋ก ๊ตฌํํ๊ธฐ (JPA) (0) | 2024.09.06 |