๋ณธ๋ฌธ์œผ๋กœ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๋ฐ˜์‘ํ˜•

ํ๋ฆ„ ์ดํ•ดํ•˜๊ธฐ

spring boot์—์„œ ๊ตฌ๊ธ€ ์†Œ์…œ ๋กœ๊ทธ์ธ ํ•˜๋Š” ๋ฐฉ๋ฒ•์˜ ๊ธฐ๋ณธ ํ๋ฆ„์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

[๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ ํด๋ฆญ]
   ↓
[๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ → redirect URI๋กœ ํ† ํฐ ๋ฐ˜ํ™˜]
   ↓
[Spring Security๊ฐ€ ํ† ํฐ ๋ฐ›์•„์„œ ์‚ฌ์šฉ์ž ์ •๋ณด ํš๋“]
   ↓
[์ž๋™ ๋กœ๊ทธ์ธ or DB ์‚ฌ์šฉ์ž ๋“ฑ๋ก]

 

์ฒ˜์Œ์—” ์„ค์ •ํ• ๊ฒƒ๋„ ๋งŽ๊ณ  ํ• ๊ฒƒ๋„ ๋งŽ์•„์„œ ๊ต‰์žฅํžˆ ๊ท€์ฐฎ๊ณ  ์ง€๋ฃจํ•˜์ง€๋งŒ ํ•œ๋ฒˆ ์ œ๋Œ€๋กœ ์ตํ˜€๋‘๋ฉด ๋‹ค๋ฅธ ์†Œ์…œ๋กœ๊ทธ์ธ๋„ ๋น„์Šทํ•œ ๊ตฌ์กฐ๊ธฐ ๋•Œ๋ฌธ์— ์ง€๊ธˆ ์ง€์‹์„ ์จ๋จน์œผ๋ฉด ๋œ๋‹ค.

 

ํด๋ผ์ด์–ธํŠธ ์•„์ด๋”” ๋งŒ๋“ค๊ธฐ

 

 

Google ํด๋ผ์šฐ๋“œ ํ”Œ๋žซํผ

๋กœ๊ทธ์ธ Google ํด๋ผ์šฐ๋“œ ํ”Œ๋žซํผ์œผ๋กœ ์ด๋™

accounts.google.com

ํ•ด๋‹น ์‚ฌ์ดํŠธ์— ์ ‘์†ํ•˜์—ฌ ์ƒˆํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  API๋ฐ ์„œ๋น„์Šค์— ๋“ค์–ด๊ฐ€ Oauth ๋™์˜ ํ™”๋ฉด์„ ์„ ํƒํ•œ๋‹ค.

์‹œ์ž‘ํ•˜๊ธฐ๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋ญ๋ญ๋ฅผ ์ ์œผ๋ผ๊ณ ํ•˜๋Š”๋ฐ

๋Œ€์ถฉ ์ ์–ด์ฃผ๊ณ  ์™„๋ฃŒํ•˜๋ฉด ๋˜๊ณ  ์•„๋ž˜ OAuth 2.0 ํด๋ผ์ด์–ธํŠธ ID ๋งŒ๋“ค๊ธฐ๋ฅผ ์„ ํƒํ•œ๋‹ค.

 

์—ฌ๊ธฐ ์Šน์ธ๋œ ๋ฆฌ๋””๋ ‰์…˜ url์— url ์ถ”๊ฐ€ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅธํ›„

http://localhost:8080/login/oauth2/code/google

๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ๋งŒ๋“ค๊ธฐ๋ฅผ ๋ˆ„๋ฅธ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ์ด๋ ‡๊ฒŒ ํด๋ผ์ด์–ธํŠธ id๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.

 

Dependencies ์ถ”๊ฐ€ํ•˜๊ธฐ

build.gradle์— dependencies์— ์•„๋ž˜์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ 

	implementation 'org.springframework.boot:spring-boot-starter-security'
	implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'

 

Properties ์ถ”๊ฐ€ํ•˜๊ธฐ

application.properties์—๋Š” ํ•ด๋‹น ์„ค์ •์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.

spring.security.oauth2.client.registration.google.client-id=๋ฐœ๊ธ‰๋ฐ›์€-client-id
spring.security.oauth2.client.registration.google.client-secret=๋ฐœ๊ธ‰๋ฐ›์€-client-secret
spring.security.oauth2.client.registration.google.scope=profile,email

spring.security.oauth2.client.provider.google.authorization-uri=https://accounts.google.com/o/oauth2/v2/auth
spring.security.oauth2.client.provider.google.token-uri=https://oauth2.googleapis.com/token
spring.security.oauth2.client.provider.google.user-info-uri=https://www.googleapis.com/oauth2/v3/userinfo
spring.security.oauth2.client.provider.google.user-name-attribute=sub

์ฐธ๊ณ ๋กœ ๋ฐœ๊ธ‰๋ฐ›์€ client-secret์€ ํŽธ์ง‘์— ๋“ค์–ด๊ฐ€๋ฉด ๋‚˜์™€์žˆ๋‹ค.

 


 

์‹œํ๋ฆฌํ‹ฐ ์„ค์ •ํ•˜๊ธฐ

์ด์ œ ๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ ํ๋ฆ„์„ ์ฒ˜๋ฆฌํ•  ์‹œํ๋ฆฌํ‹ฐ ์„ค์ •๋ถ€ํ„ฐ ํ•ด๋ณด์ž.

 

๋ชฉํ‘œ

- ๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ url ์ž๋™ ์ œ๊ณต

- ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์‹œ ์‚ฌ์šฉ์ž ์ •๋ณด ๋ฐ›์•„์„œ db ์ €์žฅ ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ

- ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํŽ˜์ด์ง€ ๋ถ„๋ฆฌ

 

JPA ์„ค์ •

jpa๋„ ์“ธ๊บผ๋ผ ์ผ๋‹จ build.gradle์— dependencies์— ํ•ด๋‹น ์ฝ”๋“œ๋„ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

๊ทธ๋‹ค์Œ application.properties์— db์ ‘์†์ •๋ณด๋‹ค jpa์„ค์ •๋„ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค

#PostgreSQL ์ ‘์† ์ •๋ณด
spring.datasource.url=jdbc:postgresql://localhost:5432/your_db_name
spring.datasource.username=your_db_user
spring.datasource.password=your_db_password
spring.datasource.driver-class-name=org.postgresql.Driver

# JPA ์„ค์ •
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect

# ํƒ€์ž„์กด ์„ค์ • (์„ ํƒ)
spring.jpa.properties.hibernate.jdbc.time_zone=Asia/Seoul

 

 

 

ํด๋”๊ตฌ์กฐ๋Š” ์ด๋Ÿฐ์‹์œผ๋กœ ํ•ด๋†จ๋‹ค.

 

์ฝ”๋“œ ์ ๊ธฐ

User entity > UserRepository > CustomOath2UserService > SecurityConfig ์ˆœ์œผ๋กœ ๋งŒ๋“ค์–ด๋ณด์ž.

 

Users

@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Users {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String email;
    private String nickname;
}

 

UserRepository

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByEmail(String email);
}

 

CustomOauth2UserService

@Service
@RequiredArgsConstructor
public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
    private final UserRepository userRepository;

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2User delegate = new DefaultOAuth2UserService().loadUser(userRequest);
        Map<String, Object> attributes = delegate.getAttributes();

        // ๊ตฌ๊ธ€ ์‚ฌ์šฉ์ž ์ •๋ณด์—์„œ email๊ณผ name ๊ฐ€์ ธ์˜ค๊ธฐ
        String email = (String) attributes.get("email");
        String name = (String) attributes.get("name");

        // ์—†์œผ๋ฉด ์ƒˆ๋กœ ์ €์žฅ
        User user = userRepository.findByEmail(email)
                .orElseGet(() -> userRepository.save(User.builder()
                        .email(email)
                        .nickname(name)
                        .build()));

        return new DefaultOAuth2User(
                Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")),
                attributes,
                "email" // attributes ์ค‘์—์„œ key๋กœ ์‚ฌ์šฉํ•  ๊ฐ’
        );
    }
}

 

SecurityConfig

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
    private final CustomOAuth2UserService customOAuth2UserService;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(csrf -> csrf.disable())
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/", "/css/**", "/js/**", "/images/**", "/login").permitAll()
                        .anyRequest().authenticated()
                )
                .oauth2Login(oauth -> oauth
                        .loginPage("/login") // ์ปค์Šคํ…€ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€
                        .defaultSuccessUrl("/dashboard", true)
                        .userInfoEndpoint(user -> user
                                .userService(customOAuth2UserService) // ์‚ฌ์šฉ์ž ์ •๋ณด ์ฒ˜๋ฆฌ ๋กœ์ง
                        )
                )
                .logout(logout -> logout
                        .logoutSuccessUrl("/")
                        .invalidateHttpSession(true)
                );

        return http.build();
    }
}

 

๋‹ค์Œ์—์„œ๋Š” ์ด์ œ ํ”„๋ก ํŠธ๋‹จ์„ ์—ฐ๊ฒฐํ•ด์„œ ์ง์ ‘ ๋กœ๊ทธ์ธ๋˜๊ฒŒ ํ•ด๋ณด์ž~~

๋ฐ˜์‘ํ˜•