[Security] OAuth2.0 ๋ก๊ทธ์ธ ํ์ฒ๋ฆฌ - ๊ถํ ๋ถ์ฌ, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ์ฅ
by rlaehddnd0422์ด ์ ํฌ์คํ ์์ OAuth2.0์ ํตํ ๊ตฌ๊ธ ์์ ๋ก๊ทธ์ธ์ ์ ์ฉํด๋ณด์์ต๋๋ค.
ํ์ง๋ง ๋จ์ํ ๋ก๊ทธ์ธ๋ง ์ฑ๊ณต ํ์ ๋ฟ ์์ง ๋จ์ ๋ฌธ์ ๋ค์ด ์์ต๋๋ค.
1. ์์ง ์์ ๋ก๊ทธ์ธ์ผ๋ก ๋ก๊ทธ์ธํ ์ฌ์ฉ์์ ๋ํ ์ ๋ณด๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์ต๋๋ค.
โถ๏ธ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์ ๋ก๊ทธ์ธํ ์ฌ์ฉ์์ ์ ๋ณด๋ฅผ ์ปค์คํ ํด์ ์ ์ฅ ํ์
2. ์์ ๋ก๊ทธ์ธํ ์ฌ์ฉ์์ ๋ํ ์ ๊ทผ ๊ถํ์ด ์ฃผ์ด์ง์ง ์์์ต๋๋ค.
โถ๏ธ ์์ ๋ก๊ทธ์ธ ์ฌ์ฉ์์ ๋ํด ์ ๊ทผ ๊ถํ ์ค์ (์ด ๋ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ ์ Role ์ค์ ์ผ๋ก์จ ํด๊ฒฐ)
์ด๋ฒ ํฌ์คํ ์์๋ ์ฃผ์ด์ง ์์ ๋ฌธ์ ๋ค์ Spring Security ๋ด๋ถ์์ ์ฒ๋ฆฌํด๋ณด๋๋ก ํฉ์๋ค!
์ผ๋ฐ ๋ก๊ทธ์ธ ๋ก์ง์ ๋ค์ ํ ๋ฒ ์ ๋ฆฌ.
1. Request โก๏ธ AuthenticationFilter
: ํด๋ผ์ด์ธํธ๊ฐ AuthenticationFilter์ ๋ฑ๋ก๋ ์์ฒญ์ ํ ๊ฒฝ์ฐ Filter๊ฐ ์ด๋ฅผ ๋์์ฑ์ ์ฒ๋ฆฌํฉ๋๋ค.
2. AuthenticationFilter โก๏ธ UsernamePasswordAuthenticationToken
: Filter์์ UsernamePasswordAuthenticationToken์๊ฒ ์ธ์ฆ ์ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ์ฌ ์ธ์ฆ์ฉ ๊ฐ์ฒด๋ฅผ ํ๋ ๋ง๋ค์ด ํํฐ์๊ฒ ๋ฆฌํดํฉ๋๋ค.
3. AuthenticationFilter โก๏ธ AuthenticationManager
: ๋ฆฌํด ๋ฐ์ ์ธ์ฆ์ฉ ๊ฐ์ฒด๋ฅผ AuthenticationManager์๊ฒ ์ ๋ฌํฉ๋๋ค.
4. AuthenticationManager โก๏ธ AuthenticationProvider
: AuthenticationManager์ ๋ฑ๋ก๋ AuthenticationProvider๋ฅผ ์ฐพ์์ ์ธ์ฆ์ฉ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํฉ๋๋ค.
5. AuthenticationProvider โก๏ธ UserDetailsService
: Provider์์ UserDetailsService์๊ฒ DB์ ์ ๊ทผํ์ฌ ์ธ์ฆ ์ ์ฐจ๋ฅผ ID์ PASSWORD๋ก ๊ฒ์ฆํ๋๋ก ์ง์ํฉ๋๋ค.
6. UserDetailsService โก๏ธ UserDetails โก๏ธ UserDetailsService
: UserDetailsService๋ ์ค์ DB์ ์ ๊ทผํ์ฌ ํด๋น ID์ PW๊ฐ ์ผ์นํ๋ ํ์์ด ์๋์ง ๊ฒ์ฌํ ์ดํ, ์์ผ๋ฉด ํด๋น ๋ฐ์ดํฐ์ ๋ํ ์ ๋ณด๋ฅผ UserDetails์ ๋ด์ ๋ฆฌํดํฉ๋๋ค.
7. UserDetailsService โก๏ธ AuthenticationProvider
: Provider์๊ฒ UserDetails๋ฅผ ์ ๋ฌํฉ๋๋ค.
8. AuthenticationProvider โก๏ธ AuthenticationManager
: Authentication ๊ฐ์ฒด ์์ UserDetails๋ฅผ ๋ด์ Authentication ๊ฐ์ฒด๋ฅผ AuthenticationManager์๊ฒ ์ ๋ฌํฉ๋๋ค.
9,10. AuthenticationManager โก๏ธ AuthenticationFilter โก๏ธ SecurityContext
: ๋ฆฌํด๋ฐ์ Authentication ๊ฐ์ฒด๋ฅผ SecurityContextHolder์ ์ ๋ฌํฉ๋๋ค.
์ด ๊ณผ์ ์ ํ ๋๋ก Authentication๊ฐ์ฒด๊ฐ SecuritContext์ ์ ์ฅ๋์ด ์ดํ๋ฆฌ์ผ์ด์ ์ ๋ฐ์ ๊ฑธ์ณ ์ ์ญ์ ์ธ ์ฐธ์กฐ๊ฐ ๊ฐ๋ฅํฉ๋๋ค!
์ด ์ ์ ๋ก๊ทธ์ธ์ ๊ตฌํํ ๋๋ Security ์ค์ ํ์ผ์ ๋ฑ๋กํ ํํฐ์์ .loginProcessingUrl("/login")์ผ๋ก ์ฒ๋ฆฌํด์ /login ์ฃผ์๊ฐ ํธ์ถ์ด ๋๋ฉด ์ํ๋ฆฌํฐ๊ฐ ๋์์ฑ์ 2~5 ๊ณผ์ ์ ์ฒ๋ฆฌํ๋๋ก ๊ตฌํํ์ต๋๋ค.
UserDetailsService๋ ์ธํฐํ์ด์ค๋ฅผ ์ง์ ๊ตฌํํ์ฌ ์ฌ์ฉํ์์ฃ .
์๋์ ๊ฐ์ด UserDetailsService์ loadUserByUsername(String username)์์ ๋ฐ๋ก DB์ ์ ๊ทผํ์ฌ ์ผ์นํ๋ ํ์ ์กฐํ๋ฅผ ํตํด UserDetails์ ์์ ํด๋์ค์ธ PrincipalDetails์ user ์ ๋ณด๋ฅผ ๋ด์ ๋ฆฌํดํ์์ต๋๋ค.
+ Password๋ ์ผ์น์ฌ๋ถ๋ฅผ ๋ฐ๋ก ๊ตฌํํ์ง ์์๋ DaoAuthenticationProvider์์ ์์์ ์ฒ๋ฆฌํด์ค๋๋ค.
// ์ํ๋ฆฌํฐ session(๋ด๋ถ Authentication(๋ด๋ถ UserDetails))
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
log.info("username = {}",username);
User user = userRepository.findByUsername(username);
if (user != null) {
return new PrincipalDetails(user);
}
return null;
}
Manager์ Provider๋ฅผ ์ง์ ๋ง๋ค์ด ๋ก๊ทธ์ธ ์ฒ๋ฆฌ๋ฅผ ๊ตฌํํ ์ฝ๋๋ ์๋ ์๋ฃ๋ฅผ ์ฐธ๊ณ
Security Context์ Authenticaiton ๊ฐ์ฒด๊ฐ ๋ด๊น์ ๊ฐ์กฐํ๊ธฐ ์ํด ์ผ๋ฐ ๋ก๊ทธ์ธ ๋ก์ง์ ๋ค์ ํ ๋ฒ ์ ๋ฆฌํด๋ณด์์ต๋๋ค.
์ผ๋ฐ ๋ก๊ทธ์ธ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก OAuth ๋ก๊ทธ์ธ ๋ํ Authentication์ Security Context์ ๋ด๋ ๊ณผ์ ์ด ํ์ํฉ๋๋ค!
๋ฆฌ์์ค ์ ๊ทผ์ ํ์ํ ์ธ์ ์ SecurityContext๊ฐ ๋ด๊ฒจ์๊ณ , SecurityContext ์์ Authentication์ด ๋ด๊ฒจ์๊ธฐ ๋๋ฌธ์, OAuth ์์ ๋ก๊ทธ์ธ ๋ํ Authentication ๊ฐ์ฒด๊ฐ ํ์ํฉ๋๋ค.
Tip : ์ฌ์ฉ์๊ฐ ์ธ์ฆ์ฒ๋ฆฌ๊ฐ ์๋ฃ๋ ํ ๋ค์ ์ฌ์ดํธ๋ฅผ ์ ์ํ์ ๋ ์ธ์ ์ ์ ์ฅ๋ SecurityContext๋ฅผ ๊บผ๋ด์ด ์์ SecurityContextHolder์ ์ ์ฅํ๊ฒ ๋๊ณ ์ด๋ ์ ์ญ์ผ๋ก SecurityContext ๋ฅผ ์ฐธ์กฐํ ์ ์๊ฒ ํ๋ ์๋ฆฌ๊ฐ ๋ฉ๋๋ค.
Authentication ๊ฐ์ฒด
Spring Security๋ ์ฌ์ค Authentication ๊ฐ์ฒด ์์๋ ์ฌ์ค UserDetails ๋ฟ๋ง ์๋๋ผ, ์์ ๋ก๊ทธ์ธ ์ ์ ๋ฅผ ์ํ OAuth2User ๊ฐ์ฒด ๋ํ ๋ด์ ์ ์๋๋ก ์ง์ํฉ๋๋ค.
์ด ์ ์ ์ผ๋ฐ ๋ก๊ทธ์ธ ๋ก์ง์์ UserDetails ๊ตฌํ์ฒด์ธ PrincipalDetails๋ฅผ ๋ง๋ค์์์ต๋๋ค.
์ฐธ๊ณ
// Security Session => Authentication => UserDetails(PrincipalDetails)
@Data
public class PrincipalDetails implements UserDetails {
private User user;
// ํด๋น User์ ๊ถํ์ ๋ฆฌํดํ๋ ๊ณณ
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> collection = new ArrayList<>();
collection.add(
new GrantedAuthority(){
@Override
public String getAuthority() {
return user.getRole();
}
});
return collection;
}
ํ์ง๋ง ์์ ๊ตฌ์กฐ๋ฅผ ์ ์ด์ฉํ๋ค๋ฉด ์ผ๋ฐ ๋ก๊ทธ์ธ๊ณผ ์์ ๋ก๊ทธ์ธ์ ๋ฐ๋ก ๋๋์ง ์๊ณ PrincipalDetails๋ก ํ์ณ์ ์ด๋ ๊ฒ ํ ๋ฒ์ ๋ฌถ์ ์ ์์ต๋๋ค!
// Security Session => Authentication => UserDetails(PrincipalDetails(user)) or OAuth2User(PrincipalDetails(user,attributes))
@Data
public class PrincipalDetails implements UserDetails, OAuth2User {
private User user;
private Map<String, Object> attributes;
// ์ผ๋ฐ ๋ก๊ทธ์ธ
public PrincipalDetails(User user) {
this.user = user;
}
// Oauth ๋ก๊ทธ์ธ
public PrincipalDetails(User user, Map<String, Object> attributes) {
this.user = user;
this.attributes = attributes;
}
...
- ์ผ๋ฐ ๋ก๊ทธ์ธ ์ ์ ์ ๊ฒฝ์ฐ, UserDetails๋ฅผ implementsํ๊ฒ ๋๋ฉด ๋ฐ๋์ ๊ถํ์ ๋ฆฌํดํ๋ getAuthorities()๋ฅผ ํฌํจํ ์ฌ๋ฌ ๋ฉ์๋๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉํ์ฌ ๊ตฌํํด์ฃผ์ด์ผ ํฉ๋๋ค.
- ์์ ๋ก๊ทธ์ธ ์ ์ ์ ๊ฒฝ์ฐ, OAuth2User๋ฅผ implementsํ๊ฒ ๋๋ฉด ๋ฐ๋์ attributes์ name์ ๋ฆฌํดํ๋ ๋ ๊ฐ์ ๋ฉ์๋๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉํ์ฌ ๊ตฌํํด์ฃผ์ด์ผ ํฉ๋๋ค.
@Override
public String getName() {
return null;
}
@Override
public Map<String, Object> getAttributes() {
return attributes;
}
- ์ ์ฒ๋ผ ์์ ๋ก๊ทธ์ธ ์ ์ ์ ์ผ๋ฐ ๋ก๊ทธ์ธ ์ ์ ๋ฅผ ์์ฑ์๋ก ๋๋์ด PrincipalDetails๋ก ํ ๋ฒ์ ๋ฌถ์ด์ ์ฒ๋ฆฌํ์์ต๋๋ค.
OAuth2User์ UserDetailsService ๊ณ์ธต ๊ฐ๋ฐ(๊ถํ ๋ถ์ฌ ๋ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ์ฅ)
์ผ๋ฐ ๋ก๊ทธ์ธ์์๋ UserDetailsService์ loadByUsernamepassword() ๋ฉ์๋์์ ์ค์ DB์ ์ ๊ทผํ์ฌ ํ์์ ์กฐํํ๊ณ UserDetails๋ฅผ ๋ฆฌํดํ์ต๋๋ค.
์์ ๋ก๊ทธ์ธ ๋ํ ๋ก์ง์ ๊ฐ์ต๋๋ค๋ง, ๋ช ํํ ์ฐจ์ด๊ฐ ํ๋ ์์ต๋๋ค.
- ์ผ๋ฐ ๋ก๊ทธ์ธ / UserDetailsService : loadUserByUsername()์์ ํ์ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก DB์์ ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ PrincipalDetails์ ์ ๋ณด๋ฅผ ๋ด์ ๋ฆฌํด
- ์์
๋ก๊ทธ์ธ / DefaultOAuth2UserService : userRequest ๊ธฐ๋ฐ ๋ฐ์ดํฐ ๊ฒ์
- ์ต์ด ๋ก๊ทธ์ธ ๊ฒฝ์ฐ : loadUser(OAuthRequest userRequest)์์ ์์ ๋ก๊ทธ์ธ ๋ฐ์ดํฐ ์ ๋ณด์ธ userRequest๋ฅผ ๊ธฐ๋ฐ์ผ๋ก DB์ ๋ฐ์ดํฐ ์ฝ์ ๋ฐ PrincipalDetails์ ์ ๋ณด๋ฅผ ๋ด์ ๋ฆฌํด
- ์ต์ด ๋ก๊ทธ์ธ์ด ์๋ ๊ฒฝ์ฐ : DB์ ๋ฐ์ดํฐ๋ฅผ ์๋ก ์ ์ฅํ์ง ์๊ณ PrincipalDetails์ ์ ๋ณด๋ฅผ ๋ด์ ๋ฆฌํด
์๋๋ ๊ตฌํ ์ฝ๋์ ๋๋ค.
@Service
@RequiredArgsConstructor
@Slf4j
public class PrincipalOauth2UserService extends DefaultOAuth2UserService {
private final UserRepository userRepository;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
// ๊ตฌ๊ธ๋ก ๋ถํฐ ๋ฐ์ userRequest์ ๋ํ ํ์ฒ๋ฆฌ ํจ์
// ํจ์ ์ข
๋ฃ์ @AuthenticationPrincipal ์ด๋
ธํ
์ด์
์ด ๋ง๋ค์ด์ง.
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
log.info("userRequest.clientRegistration : {}",userRequest.getClientRegistration());
log.info("userRequest.access_Token : {}",userRequest.getAccessToken());
log.info("userRequest.access_Token.Token_value : {}",userRequest.getAccessToken().getTokenValue());
OAuth2User oAuth2User = super.loadUser(userRequest);
// ์ request ์ ๋ณด๋ฅผ ํ ๋๋ก ๊ฐ์ ํ์๊ฐ์
์งํ
// ๊ตฌ๊ธ๋ก๊ทธ์ธ๋ฒํผ -> ๊ตฌ๊ธ๋ก๊ทธ์ธ ์ฐฝ -> ๋ก๊ทธ์ธ ์๋ฃ -> ์ฌ์ฉ์ ์ ๋ณด code๋ฅผ ๋ฆฌํด ๋ฐ์(userRequest์ ๋ด๊น) -> code๋ฅผ ํ ๋๋ก Access Token ์์ฒญ
//
// userRequest ์ ๋ณด๋ฅผ ํ ๋๋ก
// -> ํ์ ํ๋กํ์ ๋ฐ์์ผํจ (loadUser ํจ์) -> ๊ตฌ๊ธ๋ก๋ถํฐ ํ์ ํ๋กํ์ ๋ฐ์์ค
log.info("userRequest.getAttributes : {}", super.loadUser(userRequest).getAttributes());
String provider = userRequest.getClientRegistration().getRegistrationId();
String provider_id = oAuth2User.getAttribute("sub"); // provid
String email = oAuth2User.getAttribute("email");
String username = provider + provider_id; // google_sub
String password = bCryptPasswordEncoder.encode("getInthere");
String role = "ROLE_USER";
User userEntity = userRepository.findByUsername(username);
if (userEntity == null) {
userEntity = User.builder()
.username(username)
.email(email)
.password(password)
.provider(provider)
.provider_id(provider_id)
.role(role)
.build();
userRepository.save(userEntity);
} else {
log.info("์ต์ด ๋ก๊ทธ์ธ์ด ์๋๋๋ค.");
}
return new PrincipalDetails(userEntity, oAuth2User.getAttributes());
}
}
- ๊ตฌ๊ธ ๋ก๊ทธ์ธ ์ฑ๊ณต ์ดํ loadUser()์์ userRequest์ Access Token์ ์์ฒญํ code, ์ฌ์ฉ์ ์ ๋ณด๊ฐ ๋ด๊น๋๋ค.
- ๊ถํ์ธ ROLE์ "ROLE_USER"๋ก ์ค์ ํ์์ต๋๋ค. (๊ถํ ๋ถ์ฌ)
- ์ด ์ ๋ณด๋ฅผ ํ ๋๋ก ์ต์ด ๋ก๊ทธ์ธ ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ํ๊ณ , user ์ ๋ณด์, userRequest์ attributes๋ฅผ PrincipalDetails์ ๋ด์ ๋ฆฌํดํ์์ต๋๋ค.
- ์ต์ด ๋ก๊ทธ์ธ์ด ์๋ ๊ฒฝ์ฐ if๋ฌธ์ด ์คํ๋์ง ์๊ณ PrincipalDetails์ user ์ ๋ณด์ attribute๋ง ๋ด์์ ๋ฆฌํดํฉ๋๋ค.
๋ง๋ PrincipalOauthUserService๋ Filter์ ํ์ฒ๋ฆฌ ์๋น์ค๋ก ๋ฑ๋กํด ์ค์๋ค.
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, // @Secured ํ์ฑํ
prePostEnabled = true // @PreAuthorized ํ์ฑํ, @PostAuthroized ํ์ฑํ
)
public class SecurityConfig {
@Autowired
PrincipalOauth2UserService principalOauth2UserService;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/user/**").authenticated() // ์ธ์ฆ
.antMatchers("/manager/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_MANAGER')") // ์ธ์ฆ + ์ธ๊ฐ
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')") // ์ธ์ฆ + ์ธ๊ฐ
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/loginForm")
.loginProcessingUrl("/login") // login ์ฃผ์๊ฐ ํธ์ถ์ด๋๋ฉด ์ํ๋ฆฌํฐ๊ฐ ๋์์ฑ์ ๋์ ๋ก๊ทธ์ธ ์งํํด์ค.
.defaultSuccessUrl("/")
.and()
.oauth2Login()
.loginPage("/loginForm")
.userInfoEndpoint()
.userService(principalOauth2UserService); // ๊ตฌ๊ธ ๋ก๊ทธ์ธ ์ดํ ํ์ฒ๋ฆฌ
return http.build();
}
}
๋ฒ์ธ : PrincipalDetails๋ฅผ OAuth2User, UserDetails ๋ ์ธํฐํ์ด์ค๋ฅผ ์์๋ฐ์ ๊ตฌํํ ๊ฒ์ฒ๋ผ PrincipalDetailsService ๋ํ ์๋์ ํ ๊ตฐ๋ฐ์ ๋ฌถ์ด์ ๊ตฌํํ ์ ์์ต๋๋ค๋ง ๊ฐ๋ ์ฑ์ ์ํด ๋ถ๋ฆฌํ์์ต๋๋ค.
PrincipalDetailsService extends DefaultOAuth2UserService(OAuth ํ์) implements UserDetailsService(์ผ๋ฐ ํ์)
SecurityConfig
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, // @Secured ํ์ฑํ
prePostEnabled = true // @PreAuthorized ํ์ฑํ, @PostAuthroized ํ์ฑํ
)
public class SecurityConfig {
@Autowired
PrincipalDetailsService principalDetailsService;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/user/**").authenticated() // ์ธ์ฆ
.antMatchers("/manager/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_MANAGER')") // ์ธ์ฆ + ์ธ๊ฐ
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')") // ์ธ์ฆ + ์ธ๊ฐ
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/loginForm")
.loginProcessingUrl("/login") // login ์ฃผ์๊ฐ ํธ์ถ์ด๋๋ฉด ์ํ๋ฆฌํฐ๊ฐ ๋์์ฑ์ ๋์ ๋ก๊ทธ์ธ ์งํํด์ค.
.defaultSuccessUrl("/")
.and()
.oauth2Login()
.loginPage("/loginForm")
.userInfoEndpoint()
.userService(principalDetailsService); // ๊ตฌ๊ธ ๋ก๊ทธ์ธ ์ดํ ํ์ฒ๋ฆฌ
return http.build();
}
}
- userInfoEndpoint() ๋ OAuth2 ๋ก๊ทธ์ธ ์ฑ๊ณต ํ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ๋ ์ค์ ์ ๋ด๋นํฉ๋๋ค.
- ์ฆ, userInfoEndpoint().userService()๋ OAuth2 ๋ก๊ทธ์ธ ์ฑ๊ณต ํ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์จ ์ํ์์ ๋ฆฌ์์ค ์๋ฒ(Google, ๋ค์ด๋ฒ, ์นด์นด์ค ๋ฑ) ์์ ์ถ๊ฐ ์งํํ๊ณ ์ ํ๋ ๊ธฐ๋ฅ์ ๊ตฌํํฉ๋๋ค.
์ผ๋ฐ ์ ์ / OAuth ๋ฅผ ๋๋์ง ์์์ผ๋ก์จ ์๊ธฐ๋ ์ฅ์
// ์ผ๋ฐ ๋ก๊ทธ์ธ
@ResponseBody
@GetMapping("/test/normal/login")
public String loginTest(Authentication authentication, @AuthenticationPrincipal UserDetails userDetails) {
log.info("/test/normal/login ===================");
PrincipalDetails principalDetails = (PrincipalDetails) authentication.getPrincipal(); // ๋ค์ด์บ์คํ
ํ๊ฑฐ๋,
log.info("authentication : {}", principalDetails.getUser());
log.info("userDetails : {}", userDetails.getUsername()); // ์ด๋
ธํ
์ด์
์ผ๋ก ํ๊ฑฐ๋
return "์ธ์
์ ๋ณด ํ์ธํ๊ธฐ";
}
// OAuth ๋ก๊ทธ์ธ
@ResponseBody
@GetMapping("/test/oauth/login")
public String loginTestOauth(Authentication authentication, @AuthenticationPrincipal OAuth2User oauth) {
log.info("/test/oauth/login ===================");
OAuth2User oAuth2User = (OAuth2User) authentication.getPrincipal();// ๋ค์ด์บ์คํ
ํ๊ฑฐ๋,
log.info("authentication : {}", oAuth2User.getAttributes());
log.info("oauth2User : {} ", oauth.getAttributes()); // ์ด๋
ธํ
์ด์
์ผ๋ก ํ๊ฑฐ๋
return "Oauth ์ธ์
์ ๋ณด ํ์ธํ๊ธฐ";
}
- ์์์ PrincipalDetails๋ฅผ UserDetails๋ง ์์ํ์ฌ ์ผ๋ฐ ์ ์ ๋ก ์ ํํ ๊ฒ์ด ์๋, OAuth2User๊น์ง ์์ํ ๋๋ถ์ Controller์์๋ ์ด๋ ๊ฒ ์ผ๋ฐ/์์ ๋ก๊ทธ์ธ์ ์์ฒญ๋งคํ์ ๋๋์ง ์์๋ ๋ฉ๋๋ค.
// ์ผ๋ฐ ๋ก๊ทธ์ธ/OAuth ๋ก๊ทธ์ธ ๋๋์ง ์๊ณ ์์์ฒ๋ฆฌ
// UserDetails -> PrincipalDetails
// OAuthUser -> PrincipalDetails
@ResponseBody
@GetMapping("/test/login")
public String loginTest(@AuthenticationPrincipal PrincipalDetails principalDetails) {
log.info("/test/login ===================");
log.info("principalDetails : {}", principalDetails.getUser());
return "Oauth ๋๋ ์ผ๋ฐ ๋ก๊ทธ์ธ ์ธ์
์ ๋ณด ํ์ธํ๊ธฐ";
}
- ์์ ๊ฐ์ด ํ๋์ ์์ฒญ์ผ๋ก ๋ฌถ์ด์ ์ฒ๋ฆฌํ ์ ์๊ฒ ๋์์ต๋๋ค.
- OAuth2 ๋ก๊ทธ์ธ ํ์ฒ๋ฆฌ ์๋น์ค์์ ๋ฑ๋กํ @AuthenticationPricinpal ์ด๋ ธํ ์ด์ : ์ธ์ ์ ๋ณด UserDetails์ ์ ๊ทผํ ์ ์๋ ์ด๋ ธํ ์ด์ ์ผ๋ก, ๋ก๊ทธ์ธ ์ ๋ณด๋ฅผ ์ปจํธ๋กค๋ฌ ๊ณ์ธต์์ ๋ฐ์์ฌ ์ ์์ต๋๋ค.
<์ ๋ฆฌ>
- OAuth2.0์ ์ด์ฉํ ์์ ๋ก๊ทธ์ธ ์ฑ๊ณต ์ดํ ํ์ฒ๋ฆฌ(๊ถํ๋ถ์ฌ ๋ฐ ์ต์ด ๋ก๊ทธ์ธ ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฝ์ )
- OAuth๋ฅผ ์ ํํ ์ดํดํ๊ธฐ ์ํด์ ์ผ๋ฐ ๋ก๊ทธ์ธ ๋ก์ง์ ์ ์ดํดํ๋ ๊ฒ์ด ํ์์ ๋๋ค.
<์ฐธ๊ณ ์๋ฃ>
'๐ Backend > Spring Security' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Security] ์ฟ ํค vs ์ธ์ vs ํ ํฐ (0) | 2023.06.02 |
---|---|
[Security] OAuth2.0 ๋ค์ด๋ฒ, ์นด์นด์ค ๋ก๊ทธ์ธ ๊ธฐ๋ฅ ์ถ๊ฐ (0) | 2023.06.01 |
[Security] OAuth2.0์ ์ด์ฉํ ์์ ๋ก๊ทธ์ธ (๊ตฌ๊ธ) (0) | 2023.05.31 |
[Security] ๊ถํ ์ฒ๋ฆฌ @PreAuthorize, @PostAuthorize, @Secured (0) | 2023.05.29 |
[Security] Security ํ์๊ฐ์ , ๋ก๊ทธ์ธ (0) | 2023.05.29 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
Study Repository
rlaehddnd0422