Day 9
์คํ๋ง ์ํ๋ฆฌํฐ์ OAuth 2.0์ผ๋ก ๋ก๊ทธ์ธ ๊ตฌํ
์คํ๋ง ์ํ๋ฆฌํฐ
๋ง๊ฐํ ์ธ์ฆ(Authentication)๊ณผ ์ธ๊ฐ(Authorization) ๊ธฐ๋ฅ์ ๊ฐ์ง ํ๋ ์์ํฌ
์ฌ์ค์ ์คํ๋ง ๊ธฐ๋ฐ์ ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ๋ณด์์ ์ํ ํ์ค
์คํ๋ง ์ํ๋ฆฌํฐ์ ์คํ๋ง ์ํ๋ฆฌํฐ Oauth2 ํด๋ผ์ด์ธํธ
ํ์ฌ ๋ง์ ์๋น์ค์์ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ์์ ๋ก๊ทธ์ธ ์ ์ฌ์ฉ
freelec-springboot2-webservice๋ผ๋ ํ๋ก์ ํธ๋ฅผ ์์ฑ,
OAuth ๋์ํ๋ฉด์ ์์ฑํ ํ,
์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด์ redirection url์ ๋ฑ๋กํ๊ณ ์๋ก ์์ฑํ๊ฒ ๋๋ฉด
ํด๋น ํ๋ก์ ํธ์ clientId์ security์ฝ๋๊ฐ ๋์ค๊ฒ ๋๋ค
์ด์ ๋ ํ์ฌ๊น์ง ์งํํด์ค๋ ํ๋ก์ ํธ์ application-oauth ์ค์ ํ์ผ์ ๋ง๋ค์ด์ค์ผ ํจ
src/main/resources/application-oauth.properties
spring.security.oauth2.client.registration.google.client-id = "ํด๋ผ์ด์ธํธID"
spring.security.oauth2.client.registration.google.client-secret = "๋น๋ฐ์ฝ๋"
spring.security.oauth2.client.registration.google.scope = profile, email
scope = profile, email
๋ง์ ์์ ์์ ์ค์ ๋ก scope์ ๋ฑ๋กํ์ง ์๊ณ ์ฌ์ฉํ๋ค
๊ธฐ๋ณธ๊ฐ์ด openid, profile, email์ด๋ค
ํ์ง๋ง openid๋ผ๋ scope๊ฐ ์์ผ๋ฉด Open Id Provider๋ก ์ธ์ํ๊ธฐ ๋๋ฌธ์ ๋บ
์ด๋ ๊ฒ ๋๋ฉด OpenId Provider์ธ ๊ตฌ๊ธ๊ณผ ๊ทธ๋ ์ง ์์ ์๋น์ค(๋ค์ด๋ฒ/์นด์นด์ค)๋ก ๋๋ ์ OAuth2Service๋ฅผ ๋ง๋ค์ด์ผํ๋ค
์คํ๋ง ๋ถํธ์์๋ properties์ ์ด๋ฆ์ application-๊ด๋ฆฌํ ํญ๋ชฉ.properties๋ก ๋ง๋ค๊ฒ ๋๋ฉด
๊ด๋ฆฌํ ํญ๋ชฉ ์ด๋ฆ์ profile์ด ์์ฑ๋์ด ์ด๋ฅผ ๊ด๋ฆฌํ ์ ์๊ฒ๋จ
profile=๊ด๋ฆฌํ ํญ๋ชฉ ์ด๋ ๊ฒ ํธ์ถํ๋ฉด ํด๋น properties์ ์ค์ ๋ค์ ๊ฐ์ ธ์ฌ ์ ์์
application.properties ์์ application-oauth.properties๋ฅผ ํฌํจํ๋๋ก ๊ตฌ์ฑ
spring.profiles.include=oauth
์ด๋ ๊ฒ ์์์ ์ค์ ํ ๊ฐ๋ค์ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ฐ๋ฅํด์ง
์ด์ ๋ฏผ๊ฐํ ์ ๋ณด๋ค์ด ํ๋ก์ ํธ์ ๋ค์ด๊ฐ๊ฒ ๋๋ฉด์ .gitignore์ ์ถ๊ฐํด์คํ ์ฝ๋๊ฐ ์๊น
application-oauth.properties
์ถ๊ฐํด์ฃผ๊ณ commit ํ๋ฉด application-oauth.properties ์ด ํ์ผ์ stage์ ์์ฌ๋ผ์จ ๊ฒ์ ํ์ธ๊ฐ๋ฅ
๊ตฌ๊ธ ๋ก๊ทธ์ธ ์ฐ๋ํ๊ธฐ
์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๋ด๋นํ ๋๋ฉ์ธ์ธ User ํด๋์ค๋ฅผ ์์ฑ
src/main/java/com/kyu/book/springboot/domain/user
package com.kyu.book.springboot.domain.user;
import com.kyu.book.springboot.domain.BaseTimeEntity;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.management.relation.Role;
import javax.persistence.*;
@Getter
@NoArgsConstructor
@Entity
public class User extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String email;
@Column
private String picture;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private Role role;
@Builder
public User(String name, String email, String picture, Role role){
this.name = name;
this.email = email;
this.picture = picture;
this.role = role;
}
public User update(String name, String picture){
this.name = name;
this.picture = picture;
return this;
}
public String getRoleKey(){
return this.role.getKey();
}
}
@Enumerated(EnumType.STRING)
JPA๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ก ์ ์ฅํ ๋ Enum ๊ฐ์ ์ด๋ค ํํ๋ก ์ ์ฅํ ์ง๋ฅผ ๊ฒฐ์
๊ธฐ๋ณธ์ ์ผ๋ก๋ int๋ก ๋ ์ซ์๊ฐ ์ ์ฅ
์ซ์๋ก ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ก ํ์ธํ ๋ ๊ทธ ๊ฐ์ด ๋ฌด์จ ์ฝ๋๋ฅผ ์๋ฏธํ๋์ง ์ ์๊ฐ ์์
๊ทธ๋์ ๋ฌธ์์ด(EnumType.STRING)๋ก ์ ์ฅ๋ ์ ์๋๋ก ์ ์ธํฉ๋๋ค
๊ฐ ์ฌ์ฉ์์ ๊ถํ์ ๊ด๋ฆฌํ Enum ํด๋์ค Role์ ์์ฑ
src/main/java/com/kyu/book/springboot/domain/user/Role
package com.kyu.book.springboot.domain.user;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public enum Role {
GUESR("ROLE_GUEST", "์๋"),
USER("ROLE_USER", "์ผ๋ฐ ์ฌ์ฉ์");
private final String key;
private final String title;
}
์คํ๋ง ์ํ๋ฆฌํฐ์๋ ๊ถํ ์ฝ๋์ ํญ์ ROLE_ ์ด ์์ ์์ด์ผํจ
์ฝ๋๋ณ ํค ๊ฐ์ ROLE_GUEST, ROLE_USER ๋ฑ ์ผ๋ก ์ง์ ํ ์ ์์
User์ CRUD๋ฅผ ์ฑ ์์ง ์ธํฐํ์ด์ค UserRepository๋ ์์ฑ
src/main/com/kyu/book/springboot/domain/user/UserRepository
package com.kyu.book.springboot.domain.user;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByEmail(String email);
}
findByEmail
์์ ๋ก๊ทธ์ธ์ผ๋ก ๋ฐํ๋๋ ๊ฐ ์ค email์ ํตํด ์ด๋ฏธ ์์ฑ๋ ์ฌ์ฉ์์ธ์ง ์ฒ์ ๊ฐ์ ํ๋ ์ฌ์ฉ์ธ์ง ํ๋จํ๊ธฐ ์ํ ๋ฉ์๋
์คํ๋ง ์ํ๋ฆฌํฐ ์ค์
build.gradle์ ์คํ๋ง ์ํ๋ฆฌํฐ ๊ด๋ จ ์์กด์ฑ ํ๋๋ฅผ ์ถ๊ฐ
compile('org.springframework.boot:spring-boot-starter-oauth2-client')
spring-boot-starter-oauth2-client
์์ ๋ก๊ทธ์ธ ๋ฑ ํด๋ผ์ด์ธํธ์ ์ ์ฅ์์ ์์ ๊ธฐ๋ฅ ๊ตฌํ ์ ํ์ํ ์์กด์ฑ
spring-security-oauth2-client์ spring-security-oauth2-jose๋ฅผ ๊ธฐ๋ณธ์ผ๋ก ๊ด๋ฆฌํด์ค๋ค
์ค์ ์ ์๋ฃํด ์ฃผ์์ผ๋ OAuth ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํ ์์ ๋ก๊ทธ์ธ ์ค์ ์ฝ๋๋ฅผ ์์ฑ
config.authํจํค์ง๋ฅผ ์์ฑ โ ์ํ๋ฆฌํฐ ๊ด๋ จ ํด๋์ค๋ฅผ ๋ด๋ ํจํค์ง
์ค์ ์ฝ๋ ์์ฑ
src/main/java/kyu/book/springboot/config/auth/SecurityConfig
package com.kyu.book.springboot.config.auth;
import com.kyu.book.springboot.domain.user.Role;
import lombok.RequiredArgsConstructor;
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.configuration.WebSecurityConfigurerAdapter;
@RequiredArgsConstructor
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
private final CustomOAuth2UserService customOAuth2UserService;
protected void configure(HttpSecurity http) throws Exception{
http
.csrf().disable()
.headers().frameOptions().disable()
.and()
.authorizeRequests()
.antMatchers("/", "/css/**", "/images/**","/js/**", "/h2-console/**").permitAll()
.antMatchers("/api/v1/**").hasRole(Role.USER.name())
.anyRequest().authenticated()
.and()
.logout()
.logoutSuccessUrl("/")
.and()
.oauth2Login()
.userInfoEndpoint()
.userService(customOAuth2UserService);
}
}
and()ํจ์๊ฐ ๋ฌด์์ธ์ง?
@EnableWebSecurity
Spring Security ์ค์ ๋ค์ ํ์ฑํ ์์ผ์ค
csrf().disable().headers().frameOptions().disable()
h2-console ํ๋ฉด์ ์ฌ์ฉํ๊ธฐ ์ํด ํด๋น ์ต์ ๋ค์ disable
authorizeRequests
URL๋ณ ๊ถํ ๊ด๋ฆฌ๋ฅผ ์ค์ ํ๋ ์ต์ ์ ์์์
authorizeRequests๊ฐ ์ ์ธ ๋์ด์ผ๋ง antMatchers ์ต์ ์ ์ฌ์ฉ ๊ฐ๋ฅ
antMatchers
๊ถํ ๊ด๋ฆฌ ๋์์ ์ง์ ํ๋ ์ต์
URL, HTTP ๋ฉ์๋๋ณ๋ก ๊ด๋ฆฌ๊ฐ ๊ฐ๋ฅ
"/" ๋ฑ ์ง์ ๋ URL๋ค์ permitAll() ์ต์ ์ ํตํด ์ ์ฒด ์ด๋ ๊ถํ์ ์ค
"/api/v1/**" ์ฃผ์๋ฅผ ๊ฐ์ง API๋ USER๊ถํ์ ๊ฐ์ง ์ฌ๋๋ง ๊ฐ๋ฅํ๋๋ก ํ์
anyRequest
์ค์ ๋ ๊ฐ๋ค ์ด์ธ ๋๋จธ์ง URL๋ค์ ๋ํ๋
์ฌ๊ธฐ์๋ authenticated()์ ์ถ๊ฐํ์ฌ ๋๋จธ์ง URL๋ค์ ๋ชจ๋ ์ธ์ฆ๋ ์ฌ์ฉ์๋ค์๊ฒ๋ง ํ์ฉ
์ธ์ฆ๋ ์ฌ์ฉ์ ์ฆ, ๋ก๊ทธ์ธํ ์ฌ์ฉ์๋ค์ ์ด์ผ๊ธฐํจ
logout().logoutSuccessURL("/")
๋ก๊ทธ์์ ๊ธฐ๋ฅ์ ๋ํ ์ฌ๋ฌ ์ค์ ์ ์ง์ ์
๋ก๊ทธ์์ ์ฑ๊ณต ์ "/"๋ก ์ด๋
oauth2Login
OAuth2 ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ๋ํ ์ฌ๋ฌ ์ค์ ์ ์ง์ ์
userInfoEndPoint
OAuth2 ๋ก๊ทธ์ธ ์ฑ๊ณต ์ดํ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ๋์ ์ค์ ๋ค์ ๋ด๋น
userService
์์ ๋ก๊ทธ์ธ ์ฑ๊ณต ์ ํ์ ์กฐ์น๋ฅผ ์งํํ UserService ์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด๋ฅผ ํตํด์
๋ฆฌ์์ค ์๋ฒ(์์ ์๋น์ค)์์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์จ ์ํ์์ ์ถ๊ฐ๋ก ์งํํ๊ณ ์ ํ๋ ๊ธฐ๋ฅ์ ๋ช ์ ๊ฐ๋ฅ
๊ตฌ๊ธ ๋ก๊ทธ์ธ ์ดํ ๊ฐ์ ธ์จ ์ฌ์ฉ์์ ์ ๋ณด(email, name, picture ๋ฑ)์ ๊ธฐ๋ฐ์ผ๋ก ๊ฐ์
, ๋ฐ ์ ๋ณด ์์ ์ธ์
์ ์ฅ๋ฑ์ ๊ธฐ๋ฅ์ ์ง์
src/main/java/com/kyu/book/springboot/config/auth/CustomOAuth2UserService
package com.kyu.book.springboot.config.auth;
import com.kyu.book.springboot.domain.user.User;
import com.kyu.book.springboot.domain.user.UserRepository;
import lombok.RequiredArgsConstructor;
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;
@RequiredArgsConstructor
@Service
public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
private final UserRepository userRepository;
private final HttpSession httpSession;
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2UserService<OAuth2UserRequest, OAuth2User> delegate = new DefaultOAuth2UserService();
OAuth2User oAuth2User = delegate.loadUser(userRequest);
String registrationId = userRequest.getClientRegistration().getRegistrationId();
String userNameAttributeName = userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName();
OAuthAttributes attributes = OAuthAttributes.of(registrationId, userNameAttributeName, OAuth2User.getAttributes());
User user = saveOrUpdate(attributes);
httpSession.setAttribute("user", new SessionUser(user));
return new DefaultOAuth2User(Collections.singleton(new SimpleGrantedAuthority(user.getRoleKey())),attributes.getAttributes(), attributes.getNameAttributesKey());
}
private User saveOrUpdate(OAuthAttributes attribues){
User user = userRepository.findByEmail(attribues.getEmail()).map(entity -> entity.update(attributes.getName(), attributes.getPicture())).orElse(attributes.toEntity());
return userRepository.save(user);
}
}
registrationId
ํ์ฌ ๋ก๊ทธ์ธ ์งํ ์ค์ธ ์๋น์ค๋ฅผ ๊ตฌ๋ถํ๋ ์ฝ๋
์ง๊ธ๊น์ง๋ ๊ตฌ๊ธ๋ง์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ํ์์์ง๋ง ๋์ค์ ๋ค์ด๋ฒ ๋ก๊ทธ์ธ๊น์ง ์ฐ๋ ์ ๊ตฌ๋ถ์ ์ํด์ํ์
userNameAttributeName
OAuth2 ๋ก๊ทธ์ธ ์งํ ์ ํค๊ฐ ๋๋ ํ๋ ๊ฐ์ ์ด์ผ๊ธฐ = Primary Key
๊ตฌ๊ธ์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฝ๋๋ฅผ ์ง์(๊ตฌ๊ธ์ฝ๋ : sub)ํ์ง๋ง ๋ค์ด๋ฒ, ์นด์นด์ค๋ ๊ธฐ๋ณธ์ง์์ ํ์ง ์์
๋ค์ด๋ฒ ๋ก๊ทธ์ธ๊ณผ ๊ตฌ๊ธ ๋ก๊ทธ์ธ์ ๋์์ ์ง์ํ ๋ ์ฌ์ฉ
OAuthAttributes
OAuth2UserService๋ฅผ ํตํด์ ๊ฐ์ ธ์จ OAuth2User์ attribute๋ฅผ ๋ด์ ํด๋์ค
๋ค์ด๋ฒ ๋ฑ ๋ค๋ฅธ ์์ ๋ก๊ทธ์ธ๋ ์ด ํด๋์ค๋ฅผ ์ฌ์ฉ
SessionUser
์ธ์ ์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ธฐ ์ํ Dto ํด๋์ค
์ User ํด๋์ค๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ์๋ก ๋ง๋ค์ด์ ์ฐ๋์ง ์ดํ์ ์ค๋ช
๊ตฌ๊ธ ์ฌ์ฉ์ ์ ๋ณด๊ฐ ์ ๋ฐ์ดํธ ๋์์ ๋๋ฅผ ๋๋นํด์ update๊ธฐ๋ฅ๋ ๊ฐ์ด ๊ตฌํ
Dto์ ์ญํ ์ ํ๋ OAuthAttributes
src/main/java/com/kyu/book/springboot/config/auth/dto/OAuthAttributes
package com.kyu.book.springboot.config.auth.dto;
import com.kyu.book.springboot.domain.user.Role;
import com.kyu.book.springboot.domain.user.User;
import lombok.Builder;
import lombok.Getter;
import java.util.Map;
@Getter
public class OAuthAttributes {
private Map<String, Object> attributes;
private String name;
private String nameAttributeKey;
private String email;
private String picture;
@Builder
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 static OAuthAttributes of(String registrationId, String userNameAttributename, Map<String, Object> attributes){
return OAuthAttributes.builder()
.name((String)attributes.get("name"))
.email((String)attributes.get("email"))
.picture((String)attributes.get("picture"))
.attributes(attributes)
.nameAttributeKey(userNameAttributename)
.build();
}
public User toEntity(){
return User.builder().name(name).email(email).picture(picture).role(Role.GUESR).build();
}
}
of()
OAuth2User์์ ๋ฐํํ๋ ์ฌ์ฉ์ ์ ๋ณด๋ Map์ด๊ธฐ ๋๋ฌธ์ ๊ฐ ํ๋ํ๋๋ฅผ ๋ฐํํด์ผํจ
toEntity()
User์ํฐํฐ๋ฅผ ์์ฑ
OAuthAttributes์์ ์ํฐํฐ๋ฅผ ์์ฑํ๋ ์์ ์ ์ฒ์ ๊ฐ์ ํ ๋
๊ฐ์ ํ ๋์ ๊ธฐ๋ณธ ๊ถํ์ GUEST๋ก ์ฃผ๊ธฐ ์ํด์ role ๋น๋ ๊ฐ์๋ Role.GUEST๋ฅผ ์ฌ์ฉ
OAuthAttributes ํด๋์ค ์์ฑ์ด ๋๋ฌ์ผ๋ฉด ๊ฐ์ ํจํค์ง์์ SessionUserํด๋์ค๋ฅผ ์์ฑ
SessionUserํด๋์ค๋ฅผ ์ถ๊ฐ
src/main/java/com/kyu/book/springboot/config/auth/dto/SessionUser
package com.kyu.book.springboot.config.auth.dto;
import com.kyu.book.springboot.domain.user.User;
import lombok.Getter;
import java.io.Serializable;
@Getter
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();
}
}
์ธ์ฆ๋ ์ฌ์ฉ์์ ์ ๋ณด๋ง ํ์ํ๊ธฐ ๋๋ฌธ์ name, email, picture๋ง ํ๋๋ก ์ ์ธ
User ํด๋์ค๋ฅผ ์ฌ์ฉํ์ง ์๋ ์ด์
์ธ์ ์ ๋ํด์ ์ฌ์ฉํ๋ ค๊ณ ํ๋๊น User ํด๋์ค์ ์ง๋ ฌํ๋ฅผ ๊ตฌํํ์ง ์์๋ค๋ ์๋ฏธ์ ์๋ฌ๊ฐ ๋ฐ์
โ ์ด ์ ์ ํด๊ฒฐํ๊ธฐ ์ํด User ํด๋์ค์ ์ง๋ ฌํ ์ฝ๋๋ฅผ ๋ฃ์ผ๋ฉด ์ด๋ป๊ฒ ๋ ๊น?
โ์ข ๊ทธ๋ ๋ค = User ํด๋์ค๊ฐ ์ํฐํฐ์ด๊ธฐ ๋๋ฌธ
์ํฐํฐ ํด๋์ค์๋ ์ธ์ ๋ค๋ฅธ ์ํฐํฐ์ ๊ด๊ณ๊ฐ ํ์ฑ๋ ์ง ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ ์ข์ง ์๋ค
๋ง์ฝ ์์ ์ํฐํฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ค๋ฉด ์ง๋ ฌํ ๋์์ ์์๋ค๋ ํฌํจ์ด ๋๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ ์ด์, ๋ถ์ ํจ๊ณผ๊ฐ ๋ฐ์
โ ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๊ทธ๋ฅ ์ง๋ ฌํ ๊ธฐ๋ฅ์ ๊ฐ์ง ์ธ์ dto๋ฅผ ํ๋ ์ถ๊ฐ๋ก ๋ง๋๋ ๊ฒ์ด ๋ ์ข์
๋ก๊ทธ์ธ ํ
์คํธ
src/main/resources/templates/index.mustache
{{>layout/header}}
<h1>์คํ๋ง ๋ถํธ๋ก ์์ํ๋ ์น ์๋น์ค</h1>
<div class="col-md-12">
<div class="col-md-6">
<a href="/posts/save" role="button" class="btn btn-primary">๊ธ ๋ฑ๋ก</a>
{{#userName}}
Logged in as: <span id="user">{{userName}}</span>
<a href="/logout" class="btn btn-info active" role="button">Logout</a>
{{/userName}}
{{^userName}}
<a href="/oauth2/authorization/google" class="btn btn-success active" role="button">Google</a>
{{/userName}}
</div>
<br>
...
{{#userName}}
๋จธ์คํ ์น๋ ๋ค๋ฅธ ์ธ์ด์ ๊ฐ์ if๋ฌธ์ ์ ๊ณตํ์ง ์์ต๋๋ค
true/false ์ฌ๋ถ๋ง ํ๋จํจ
๋จธ์คํ ์น์์๋ ํญ์ ์ต์ข ๊ฐ์ ๋๊ฒจ์ค์ผ ํ๋ค
userName์ด ์๋ค๋ฉด userName์ ๋ ธ์ถ์ํค๋๋ก ๊ตฌ์ฑ
a href="/logout"
์คํ๋ง ์ํ๋ฆฌํฐ์์ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณตํ๋ ๋ก๊ทธ์์ URL
๊ฐ๋ฐ์๊ฐ ๋ณ๋๋ก logout์ ํด๋นํ๋ ์ปจํธ๋กค๋ฌ๋ฅผ ๋ง๋ค ํ์๊ฐ ์์
SecurityConfig๋ฅผ ํตํด์ url๋ฅผ ๋ณ๊ฒฝํ ์๋ ์์ง๋ง ๊ธฐ๋ณธ URL์ผ๋ก ์ถฉ๋ถํ๋ค
{{^userName}}
๋จธ์คํ ์น์์ ํด๋น ๊ฐ์ด ์กด์ฌํ์ง ์๋ ๊ฒฝ์ฐ์๋ ^์ ์ฌ์ฉ
์ฌ๊ธฐ์์๋ userName์ด ์๋ค๋ฉด ๋ก๊ทธ์ธ ๋ฒํผ์ ๋ ธ์ถ์ํจ๋ค๋ ์๋ฏธ
a href="/oauth2/authorization/google"
์คํ๋ง ์ํ๋ฆฌํฐ์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ๋ ๋ก๊ทธ์ธ URL
๋ก๊ทธ์์ URL๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ๊ฐ๋ฐ์๊ฐ ๋ณ๋์ ์ปจํธ๋กค๋ฌ๋ฅผ ๋ง๋ค ํ์๊ฐ ์์
์ด์ ๋ index.mustache์์ userName์ ์ฌ์ฉํ ์ ์๋๋ก ํ๊ธฐ ์ํด์๋ IndexController์์ userName์ model์ ์ ์ฅํ๋ ์ฝ๋๋ฅผ ์ถ๊ฐ
src/main/java/com/kyu/book/springboot/web/dto/IndexController
@GetMapping("/")
public String index(Model model){
model.addAttribute("posts", postsService.findAllDesc());
SessionUser user = (SessionUser)httpSession.getAttribute("user");
if(user != null){
model.addAttribute("username", user.getName());
}
return "index";
}
(SessionUser)httpSession.getAttribute("user")
์ ์ ์์ฑ๋ CustomOAuth2UserService์์ ๋ก๊ทธ์ธ ์ฑ๊ณต์ ์ธ์ ์ SessionUser๋ฅผ ์ ์ฅํ๋๋ก ๊ตฌ์ฑ
๋ก๊ทธ์ธ ์ฑ๊ณต โ httpSession.getAttribute("user")๋ก ๊ฐ์ ๊ฐ์ ธ์ด
if(userโ null)
์ธ์ ์ ์ง์ ํ ๊ฐ์ด ์์ ๋๋ง model์ userName์ผ๋ก ๋ฑ๋ก
์ธ์ ์ ์ ์ฅ๋ ๊ฐ์ด ์๋ค๋ฉด index.mustache์์ ๋ก๊ทธ์ธ ๋ฒํผ์ด ๋ณด์ด์ง ์๋๋ก ํด๋
์ด๋ ๊ฒ๊น์ง ํ๊ณ
์ ํ๋ฆฌ์ผ์ด์ ์ ์คํ์ํค๊ณ โ login์ ํด๋ณด์ โ ๊ตฌ๊ธ๋ก๊ทธ์ธapi๋ก ๋์ด๊ฐ๊ณ โ ๋ก๊ทธ์ธํ๊ฒ๋๋ฉด โ h2-console๋ก ์ ๊ทผํด์ user table์ ํ์๊ฐ์ ๋์๊ณ โ ์ ์์ ์ผ๋ก ์ด๋ฆ์ ๊ฐ์ ธ์์ ์ด๋ฆ์ ํ์ํด์ค๋ค
ํ์ง๋ง ์ฌ๊ธฐ์์ ๊ธ์ฐ๋๊ฑด ์๋๋๋ฐ(json์์ ์๋ฌ๊ฐ 403๊ฐ ๋์ค๊ฒ ๋จ) โ ์ด๊ฑด ๊ถํ์ user๋ก ๋ง์ถฐ๋์๊ธฐ ๋๋ฌธ์ด๋ค โ h2-console๋ก ์ ๊ทผํด์
update user set role='USER';
๋ก ๊ถํ์ USER๋ก ๋ณ๊ฒฝํด์ฃผ๊ณ โ ๋ค์ ๋ก๊ทธ์ธํ๊ณ ๊ธ์ฐ๊ธฐํด๋ณด๋ฉด ์ ์์ ์ผ๋ก ๊ฐ๋ฅ!
Last updated
Was this helpful?