์ ๋ฒ ์๊ฐ์๋ ์ง์ ์ปจํธ๋กค๋ฌ์์ ์์ฒญ์ ๊ตฌํํ์ฌ์ OAuth2 ์ธ์ฆ์ ์ฒ๋ฆฌํด๋ดค์ต๋๋ค. ์ด๋ฒ ์๊ฐ์๋ OAuth2-client ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํด์, ์์ ๋ก๊ทธ์ธ API๋ฅผ ๊ตฌํํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
๊ฐ๋ฐ ํ๊ฒฝ
- IntelliJ IDEA
- Spring Boot 2.4.4
- Java 11
- Spring JPA
- Maven 3.6.3
Maven ์์กด์ฑ ์ถ๊ฐ
spring-boot-starter-oauth2-client๋ผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๊ตฌ๊ธ,ํ์ด์ค๋ถ ๊ฐ์ ๋ก๊ทธ์ธ์ ํตํ ์ธ์ฆ๊ณผ ๊ถํ ์ฒ๋ฆฌ๋ฅผ ์ฝ๊ฒ ํ ์ ์๊ฒ ํด์ค๋ค.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
spring security ์์กด์ฑ์ ์ถ๊ฐํ๋ฉด, ์คํ๋ง ๋ถํธ๋ ๊ทธ ์คํ๋ง ์ํ๋ฆฌํฐ ์๋์ค์ ์ ์ ์ฉ์ ํด์ค์, ๋ชจ๋ ์์ฒญ์ ๋ํด์ ์ธ์ฆ์ ํ์๋ก ํ๊ฒ ๋ฉ๋๋ค. (์ผ๋ถ url์ ํ์ฉํ๋ ค๋ฉด, WebSecurityConfigurerAdaptre๋ฅผ ๊ตฌํํ์ฌ ์ค์ ์ ํด์ฃผ๋ฉด ๋ฉ๋๋ค. ์ด ๋ถ๋ถ์ ์๋์์ ์์ธํ๊ฒ ์ดํด๋ณด๊ฒ ์ต๋๋ค.)
application-oauth.properties ์์ฑ + .gitignore ๋ฑ๋กํ๊ธฐ
application.properties ์ ๊ฐ์ ์์น์ ์๋ก์ด ํ์ผ์ ์์ฑํฉ๋๋ค.
application-oauth.properties๋ผ๋ ํ์ผ์ ์์ฑํ๊ณ , ์ด์ ์ ๋ฐ๊ธ๋ฐ์ ํด๋ผ์ด์ธํธ ID์ ๋น๋ฐ๋ฒํธ๋ฅผ ๋ฃ์ด์ค๋๋ค.
application-oauth.properties
๋ํ์ ์ผ๋ก spring security์์ ์ ๊ณตํ๋ oauth2-client ๋ผ์ด๋ธ๋ฌ๋ฆฌ์๋ ์ ๋ช ํ google, facebook, twitter ๋ฑ ์น์ฌ์ดํธ์ ๋ํ provider๋ค์ ์ ๊ณต์ ํด์ฃผ์ง๋ง, ์ฐ๋ฆฌ๋๋ผ์์๋ง ํ์ ์ ์ผ๋ก ์ฌ์ฉํ๋ ๋ค์ด๋ฒ๋, ์นด์นด์ค ๊ฐ์ ์๋น์ค์ ๋ํ ์ ๋ณด๋ค์ ์ ๊ณตํด์ฃผ์ง ๋ชปํ๋ค. ๊ทธ๋์ ์ฐ๋ฆฌ๊ฐ ์ง์ ๋ฑ๋ก์ ํด์ค ๊ฒ์ ๋๋ค!
# GOOGLE
spring.security.oauth2.client.registration.google.client-id = [ํด๋ผ์ด์ธํธ id]
spring.security.oauth2.client.registration.google.client-secret = [ํด๋ผ์ด์ธํธ pw]
spring.security.oauth2.client.registration.google.scope = profile, email
# ๊ตฌ๊ธ์ด๋ ํ์ด์ค๋ถ์ ์์ ์ด๋ ๋๋๋ฐ, ๋ค์ด๋ฒ๋ ์นด์นด์ค๋ ์ ์ด์ค์ผํจ(๊ธฐ๋ณธ ์ ๊ณต provider๊ฐ ์๋๊ธฐ ๋๋ฌธ์)
spring.security.oauth2.client.registration.naver.client-id = [ํด๋ผ์ด์ธํธ id]
spring.security.oauth2.client.registration.naver.client-secret= [ํด๋ผ์ด์ธํธ pw]
spring.security.oauth2.client.registration.naver.client-name=Naver
spring.security.oauth2.client.registration.naver.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.naver.redirect-uri=http://localhost:8080/login/oauth2/code/naver
# Naver Provider ๋ฑ๋ก!
spring.security.oauth2.client.provider.naver.authorization-uri=https://nid.naver.com/oauth2.0/authorize
spring.security.oauth2.client.provider.naver.token-uri=https://nid.naver.com/oauth2.0/token
spring.security.oauth2.client.provider.naver.user-info-uri=https://openapi.naver.com/v1/nid/me
spring.security.oauth2.client.provider.naver.user-name-attribute=response # ๋ค์ด๋ฒ๊ฐ ํ์์ ๋ณด๋ฅผ json์ผ๋ก ๋๊ฒจ์ฃผ๋๋ฐ, response๋ผ๋ ํค๊ฐ์ผ๋ก ๋ฆฌํดํด์ค๋ค.
# KAKAO
spring.security.oauth2.client.registration.kakao.client-id = [ํด๋ผ์ด์ธํธ id]
spring.security.oauth2.client.registration.kakao.client-secret = [ํด๋ผ์ด์ธํธ pw]
spring.security.oauth2.client.registration.kakao.redirect-uri=http://localhost:8080/login/oauth2/code/kakao
spring.security.oauth2.client.registration.kakao.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.kakao.scope=profile,account_email
spring.security.oauth2.client.registration.kakao.client-name=kakao
spring.security.oauth2.client.registration.kakao.client-authentication-method=POST
## kAKAO Provider ๋ฑ๋ก!
spring.security.oauth2.client.provider.kakao.authorization-uri= https://kauth.kakao.com/oauth/authorize
spring.security.oauth2.client.provider.kakao.token-uri=https://kauth.kakao.com/oauth/token
spring.security.oauth2.client.provider.kakao.user-info-uri=https://kapi.kakao.com/v2/user/me
spring.security.oauth2.client.provider.kakao.user-name-attribute=id # ์นด์นด์ค๊ฐ ํ์์ ๋ณด๋ฅผ json์ผ๋ก ๋๊ฒจ์ฃผ๋๋ฐ, id๋ผ๋ ํค๊ฐ์ผ๋ก ๋ฆฌํดํด์ค๋ค.
application.properties ๋ฑ๋ก
ํ์ผ๋ช ์ application-XXX.properties ๋ก ์ง์ผ๋ฉด, XXX ๋ถ๋ถ์ ์๋์ฒ๋ผ ์ฌ์ฉํ ์ ์๋ค.
# application-oauth.properties
spring.profiles.includes = oauth
.gitignore
๋ฐ๊ธ ๋ฐ์ ํด๋ผ์ด์ธํธ id, pw๊ฐ ๋ค์ด์๊ธฐ ๋๋ฌธ์ .gitignore์ ์ถ๊ฐํด์ค๋๋ค.
์์ ๋ก๊ทธ์ธ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๋ด์ ๋ณ๋์ User ํด๋์ค๋ฅผ ์์ฑํ์์ต๋๋ค.
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String email;
private String picture;
private String role = "ROLE_USER";
public User(String name, String email, String picture) {
this.name = name;
this.email = email;
this.picture = picture;
}
public User update(String name, String picture) {
this.name = name;
this.picture = picture;
return this;
}
// .. getter, setter ์๋ต
}
UserRepository๋ ์์ฑํด์ค๋๋ค.
email์ ์ด์ฉํด์ ์ฐพ์ ์ ์๋๋ก findByEmail ๋ ๋ง๋ค์ด์ค๋๋ค.
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByEmail(String email);
}
์คํ๋ง ์ํ๋ฆฌํฐ ์ค์
@Configuration
@EnableWebSecurity // ํด๋น ์ ๋
ธํ
์ด์
์ ๋ถ์ธ ํํฐ(ํ์ฌ ํด๋์ค)๋ฅผ ์คํ๋ง ํํฐ์ฒด์ธ์ ๋ฑ๋ก.
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// ์ปค์คํ
ํ OAuth2UserService DI.
@Autowired
private CustomOAuth2UserService customOAuth2UserService;
// encoder๋ฅผ ๋น์ผ๋ก ๋ฑ๋ก.
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
// WebSecurity์ ํํฐ๋ฅผ ๊ฑฐ๋ ๊ฒ ํจ์ฌ ๋น ๋ฆ. HttpSecrity์ ํํฐ๋ฅผ ๊ฑธ๋ฉด, ์ด๋ฏธ ์คํ๋ง ์ํ๋ฆฌํฐ ๋ด๋ถ์ ๋ค์ด์จ ์ํ๊ธฐ ๋๋ฌธ์..
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().mvcMatchers("/members/**","/image/**"); // /image/** ์๋ ๋ชจ๋ ํ์ผ๋ค์ ์ํ๋ฆฌํฐ ์ ์ฉ์ ๋ฌด์ํ๋ค.
web.ignoring().requestMatchers(PathRequest.toStaticResources().atCommonLocations()); // ์ ์ ์ธ ๋ฆฌ์์ค๋ค์ ๋ํด์ ์ํ๋ฆฌํฐ ์ ์ฉ ๋ฌด์.
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest() // ๋ชจ๋ ์์ฒญ์ ๋ํด์ ํ์ฉํ๋ผ.
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/") // ๋ก๊ทธ์์์ ๋ํด์ ์ฑ๊ณตํ๋ฉด "/"๋ก ์ด๋
.and()
.oauth2Login()
.defaultSuccessUrl("/login-success")
.userInfoEndpoint()
.userService(customOAuth2UserService); // oauth2 ๋ก๊ทธ์ธ์ ์ฑ๊ณตํ๋ฉด, ์ ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์ฐ๋ฆฌ๊ฐ ์์ฑํ
// customOAuth2UserService์์ ์ฒ๋ฆฌ๋ฅผ ํ๊ฒ ๋ค. ๊ทธ๋ฆฌ๊ณ "/login-success"๋ก ์ด๋ํ๋ผ.
}
}
- @EnableWebSecurity
- @Configuration ์ ๋ ธํ ์ด์ ์ ๋ถ์ธ ํด๋์ค์ ๋ถ์ด๊ณ , WebSecurityConfigurerAdapter๋ฅผ ์์๋ฐ์ผ๋ฉด, Spring Security ์ค์ ํด๋์ค๊ฐ ๋ฉ๋๋ค.
- BCryptPasswordEncoder๋ Spring Security์์ ์ ๊ณตํ๋ ์ํธํ ๊ฐ์ฒด์ ๋๋ค.
- configure(WebSecurity web)
- websecurity๋ FilterChainProxy๋ฅผ ์์ฑํ๋ ํํฐ์ ๋๋ค.
- web.ignoring().requestMatchers(PathRequest.toStaticResources().atCommonLocations());
- /css/** , /js/** ๊ฐ์ ์ ์ ๋ฆฌ์์ค ํ์ผ๋ค์ Spring Security๊ฐ ๋ฌด์ํ ์ ์๋๋ก, ํต๊ณผ์์ผ์ฃผ๋ ๊ฒ์ด ์ข์ต๋๋ค.
- configure(HttpSecurity http)
- httpSecurity๋ฅผ ํตํด HTTP ์์ฒญ์ ๋ํ ์น ๊ธฐ๋ฐ ๋ณด์์ ๊ตฌ์ฑํ ์ ์์ต๋๋ค.
- autorizeRequests()
- .antMatchers("/**").permitAll().hasRole("ADMIN"); ์ด๋ ๊ฒ ํด์ฃผ๋ฉด, "/**" ๋ก ๋ค์ด์จ ์์ฒญ์ ๋ํด์ ๊ถํ์ด ADMIN์ผ ๋, ํ์ฉ์ ํด์ฃผ๊ฒ ๋ค๋ ๋ป์ ๋๋ค.
- .anyRequest().permitAll() -> ๋ชจ๋ ์ฌ์ฉ์์ ๋ํด์ ํ์ฉํ๊ฒ ๋ค.
- .anyRequest().authenticated() -> ๋ชจ๋ ์ฌ์ฉ์์ ๋ํด์ ์ธ์ฆ ์์ฒญํ๊ฒ ๋ค.
- formlogin()
- HttpSession์ ์ด์ฉํ, form ๋ก๊ทธ์ธ์ ์ฒ๋ฆฌํ๋ ๋ฉ์๋์ ๋๋ค.
- "/login"์ ์ ๊ทผํ๋ฉด, Spring security๊ฐ ์ ๊ณตํ๋ ๋ก๊ทธ์ธ์ ์ด์ฉํ ์ ์์ต๋๋ค.
- .loginPage("/customLogin")
- ์ปค์คํ ๋ก๊ทธ์ธ ํผ์ ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด ํด๋น ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
- .defaultSuccessUrl("/{success-url}")
- ๋ก๊ทธ์ธ์ด ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋์์ ๋, ์ด๋๋๋ ํ์ด์ง์ ๋๋ค.
- logout()
- ๋ก๊ทธ์์์ ์ฒ๋ฆฌํ๋ ๋ฉ์๋์ ๋๋ค.
- "/logout"์ ์ ๊ทผํ๋ฉด, Spring Security๊ฐ Http ์ธ์ ์ ์ ๊ฑฐํด์ค๋๋ค.
- .logoutRequestMatcher(new AntPathRequestMatcher("/user/logout"))
- ๋ก๊ทธ์์์ url์ ์ค์ ํ ์ ์์ต๋๋ค.
- .exceptionHandling().accessDeniedPage("/logout/denied")
- ๋ก๊ทธ์์ ์ ์์ธ ๋ฐ์ํ์ ๋, ํด๋น ๋ฉ์๋๋ก ํธ๋ค๋งํ ์ ์์ต๋๋ค.
- oauth2Login()
- ouath2 ๋ก๊ทธ์ธ์ ํ ๋, ์ฒ๋ฆฌํ๋ ๋ฉ์๋์ ๋๋ค.
- .defaultSuccessUrl("/{login-success-url}")
- oauth2 ์ธ์ฆ์ด ์ฑ๊ณตํ์ ๋, ์ด๋๋๋ url์ ์ค์ ํ ์ ์์ต๋๋ค.
- userInfoEndPoint().userService(customOAuth2UserService);
- ๋ก๊ทธ์ธ์ด ์ฑ๊ณตํ๋ฉด, ํด๋น ์ ์ ์ ์ ๋ณด๋ฅผ ๋ค๊ณ customOAuth2UserService์์ ํ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ๊ฒ ๋ค๋ ๋ป์ ๋๋ค.
OAuth2UserService ๊ตฌํํ๊ธฐ
package me.isunghan.loginspring.security;
import me.isunghan.loginspring.repository.MemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpSession;
import java.util.Collections;
@Service
public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
@Autowired
private UserRepository userRepository;
@Autowired
private HttpSession httpSession;
@Override
public OAuth2User loadUser(OAuth2UserRequest oAuth2UserRequest) throws OAuth2AuthenticationException {
OAuth2UserService oAuth2UserService = new DefaultOAuth2UserService();
OAuth2User oAuth2User = oAuth2UserService.loadUser(oAuth2UserRequest);
// ํ์ฌ ์งํ์ค์ธ ์๋น์ค๋ฅผ ๊ตฌ๋ถํ๊ธฐ ์ํด ๋ฌธ์์ด๋ก ๋ฐ์. oAuth2UserRequest.getClientRegistration().getRegistrationId()์ ๊ฐ์ด ๋ค์ด์๋ค. {registrationId='naver'} ์ด๋ฐ์์ผ๋ก
String registrationId = oAuth2UserRequest.getClientRegistration().getRegistrationId();
// OAuth2 ๋ก๊ทธ์ธ ์ ํค ๊ฐ์ด ๋๋ค. ๊ตฌ๊ธ์ ํค ๊ฐ์ด "sub"์ด๊ณ , ๋ค์ด๋ฒ๋ "response"์ด๊ณ , ์นด์นด์ค๋ "id"์ด๋ค. ๊ฐ๊ฐ ๋ค๋ฅด๋ฏ๋ก ์ด๋ ๊ฒ ๋ฐ๋ก ๋ณ์๋ก ๋ฐ์์ ๋ฃ์ด์ค์ผํจ.
String userNameAttributeName = oAuth2UserRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName();
// OAuth2 ๋ก๊ทธ์ธ์ ํตํด ๊ฐ์ ธ์จ OAuth2User์ attribute๋ฅผ ๋ด์์ฃผ๋ of ๋ฉ์๋.
OAuthAttributes attributes = OAuthAttributes.of(registrationId, userNameAttributeName, oAuth2User.getAttributes());
User user = saveOrUpdate(attributes);
httpSession.setAttribute("user", new SessionUser(user));
System.out.println(attributes.getAttributes());
return new DefaultOAuth2User(Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))
, attributes.getAttributes()
, attributes.getNameAttributeKey());
}
// ํน์ ์ด๋ฏธ ์ ์ฅ๋ ์ ๋ณด๋ผ๋ฉด, update ์ฒ๋ฆฌ
private User saveOrUpdate(OAuthAttributes attributes) {
User user = userRepository.findByEmail(attributes.getEmail())
.map(entity -> entity.update(attributes.getName(), attributes.getPicture()))
.orElse(attributes.toEntity());
return userRepository.save(user);
}
}
OAuth2Attributes ํด๋์ค ์์ฑ
OAuth2 ๋ก๊ทธ์ธ์ ํตํด์ ๊ฐ์ ธ์จ OAuth2User์ ์ ๋ณด๋ฅผ ๋ด์์ฃผ๊ธฐ ์ํ ํด๋์ค๋ฅผ ์์ฑํฉ๋๋ค.
public class OAuthAttributes {
private Map<String, Object> attributes;
private String nameAttributeKey;
private String name;
private String email;
private String picture;
public OAuthAttributes(Map<String, Object> attributes, String nameAttributeKey, String name, String email, String picture) {
this.attributes = attributes;
this.nameAttributeKey = nameAttributeKey;
this.name = name;
this.email = email;
this.picture = picture;
}
public OAuthAttributes() {
}
// ํด๋น ๋ก๊ทธ์ธ์ธ ์๋น์ค๊ฐ kakao์ธ์ง google์ธ์ง ๊ตฌ๋ถํ์ฌ, ์๋ง๊ฒ ๋งคํ์ ํด์ฃผ๋๋ก ํฉ๋๋ค.
// ์ฌ๊ธฐ์ registrationId๋ OAuth2 ๋ก๊ทธ์ธ์ ์ฒ๋ฆฌํ ์๋น์ค ๋ช
("google","kakao","naver"..)์ด ๋๊ณ ,
// userNameAttributeName์ ํด๋น ์๋น์ค์ map์ ํค๊ฐ์ด ๋๋ ๊ฐ์ด๋ฉ๋๋ค. {google="sub", kakao="id", naver="response"}
public static OAuthAttributes of(String registrationId, String userNameAttributeName, Map<String, Object> attributes) {
if (registrationId.equals("kakao")) {
return ofKakao(userNameAttributeName, attributes);
} else if (registrationId.equals("naver")) {
return ofNaver(userNameAttributeName,attributes);
}
return ofGoogle(userNameAttributeName, attributes);
}
private static OAuthAttributes ofKakao(String userNameAttributeName, Map<String, Object> attributes) {
Map<String, Object> kakao_account = (Map<String, Object>) attributes.get("kakao_account"); // ์นด์นด์ค๋ก ๋ฐ์ ๋ฐ์ดํฐ์์ ๊ณ์ ์ ๋ณด๊ฐ ๋ด๊ธด kakao_account ๊ฐ์ ๊บผ๋ธ๋ค.
Map<String, Object> profile = (Map<String, Object>) kakao_account.get("profile"); // ๋ง์ฐฌ๊ฐ์ง๋ก profile(nickname, image_url.. ๋ฑ) ์ ๋ณด๊ฐ ๋ด๊ธด ๊ฐ์ ๊บผ๋ธ๋ค.
return new OAuthAttributes(attributes,
userNameAttributeName,
(String) profile.get("nickname"),
(String) kakao_account.get("email"),
(String) profile.get("profile_image_url"));
}
private static OAuthAttributes ofNaver(String userNameAttributeName, Map<String, Object> attributes) {
Map<String, Object> response = (Map<String, Object>) attributes.get("response"); // ๋ค์ด๋ฒ์์ ๋ฐ์ ๋ฐ์ดํฐ์์ ํ๋กํ ์ ๋ณด๋ค ๋ด๊ธด response ๊ฐ์ ๊บผ๋ธ๋ค.
return new OAuthAttributes(attributes,
userNameAttributeName,
(String) response.get("name"),
(String) response.get("email"),
(String) response.get("profile_image"));
}
private static OAuthAttributes ofGoogle(String userNameAttributeName, Map<String, Object> attributes) {
return new OAuthAttributes(attributes,
userNameAttributeName,
(String) attributes.get("name"),
(String) attributes.get("email"),
(String) attributes.get("picture"));
}
// .. getter/setter ์๋ต
public User toEntity() {
return new User(name, email, picture);
}
}
์์ ์๋น์ค๋ง๋ค ์ ๋ณด๋ค์ ๊ฐ์ด ๋ค ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ์ง์ ๊ฐ์ print๋ก ์ฐ์ด๋ณด๋ฉด์ ์ค์ ํด์ผ ๋ฉ๋๋ค.
๋ค์ด๋ฒ์ ๊ฒฝ์ฐ response๊ฐ ์์ ํ๋กํ ์ ๋ณด๊ฐ ๋ค์ด์์ด์ map์์ "response" ํค ๊ฐ์ ์ด์ฉํด ๊ฐ์ ๊บผ๋๊ณ ,
๊ฐ ์๋น์ค์์ ๋ณด๋ด์ค ํ๋กํ ์ ๋ณด๋ค์ key๊ฐ์ด naver์ ํ๋กํ์ฌ์ง url์ profile_image์ด๊ณ , google์ picture ๋ฑ๋ฑ.. ์ด์ง ์ด์ง ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ๊ฐ์ ์ ์ค์ ํด์ค์ผ ํฉ๋๋ค.
SessionUser ํด๋์ค ์์ฑ
SessionUser๋ ์ธ์ฆ๋ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์ ์ฅํ๋ Dto ํด๋์ค์ ๋๋ค. HttpSession์ ๋ฃ์ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ง๋ ฌํ๋ฅผ ํด์ค๋๋ค.
import java.io.Serializable;
public class SessionUser implements Serializable {
private String name;
private String email;
private String picture;
public SessionUser(User user) {
this.name = user.getName();
this.email = user.getEmail();
this.picture = user.getPicture();
}
public SessionUser() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPicture() {
return picture;
}
public void setPicture(String picture) {
this.picture = picture;
}
}
๋ก๊ทธ์ธ ๋ฒํผ ์์ฑ
- "/oauth2/authorization/google"
- Spring security์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ๋ url์ ์ฌ์ฉํฉ๋๋ค.
<a href="/oauth2/authorization/google">๊ตฌ๊ธ ์์ด๋๋ก ๋ก๊ทธ์ธ</a>
<a href="/oauth2/authorization/naver">๋ค์ด๋ฒ ์์ด๋๋ก ๋ก๊ทธ์ธ</a>
<a href="/oauth2/authorization/kakao">์นด์นด์ค ์์ด๋๋ก ๋ก๊ทธ์ธ</a>
๊ฐ์ฌํฉ๋๋ค!
REFERENCES