본문 바로가기

Server/Java, Spring

Spring Security Oauth2 Google 로그인

 

 

Spring Security

: 인증과 접근 제어를 위해 세부적인 맞춤 구성이 가능한 강력한 프레임워크

 

OAuth2 (Open Authorization 2)

: 사용자가 비밀번호를 제공하지 않고 타사 애플리케이션의 사용자 정보를 접근할 수 있도록 허용하는 표준 인증 프로토콜

 

 


 

 

 

1️⃣ Spring Security에서 OAuth2 Google 로그인하기

 

Spring Security는 SecurityFilterChain@Bean으로 등록하여 보안 설정을 적용합니다.

 

pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

 

 

SecurityConfig.java

package com.koa.SpringOauth2Demo;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity // Spring Security 설정 활성화 어노테이션 (사용자가 직접 보안 설정 시 필요)
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        http
                .authorizeHttpRequests(auth->auth.anyRequest().authenticated()) // anyRequest를 authenticated 설정
                .oauth2Login(Customizer.withDefaults()); // OAuth2 로그인 사용

        return http.build();
    }

}

 

 

Google cloud에서 발급받은 client id, client secret 정보를 넣어주세요.

 

application.properties

spring.security.oauth2.client.registration.google.client-id={your-client-id}
spring.security.oauth2.client.registration.google.client-secret={your-client-secret}

 

 

실행하면 아래와 같이 구글 로그인이 가능하게 생성됩니다.

 

 

Spring Security를 사용하면 기본적으로 /login 경로에 로그인 페이지가 자동으로 생성됩니다.

 


 

2️⃣ OAuth2 로그인 후 정보 가져오기

 

Spring Security에서 OAuth2 사용자 OAuth2User 인터페이스를 구현한 클래스를 만듭니다.

이는 OAuth2 제공자한테 받은 정보(attributes), 권한(authorities), 이름(name)을 관리하는 역할을 합니다.

 

User.java

*Spring Security에서 기본적으로 제공하는 DefaultOAuth2User 클래스도 있습니다.

package com.koa.SpringOauth2Demo;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.core.user.OAuth2User;

import java.util.Collection;
import java.util.Map;

public class User implements OAuth2User {
    private final Collection<? extends GrantedAuthority> authorities; // 권한 목록
    private final Map<String, Object> attributes; // 정보
    private final String nameAttributeKey; // 식별 키

    public User(Collection<? extends GrantedAuthority> authorities, Map<String, Object> attributes, String nameAttributeKey) {
        this.authorities = authorities;
        this.attributes = attributes;
        this.nameAttributeKey = nameAttributeKey;
    }

    @Override
    public Map<String, Object> getAttributes() {
        return attributes;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    @Override
    public String getName() {
        return attributes.get(nameAttributeKey).toString();
    }
}

 

 

Spring Security의 DefaultOAuth2UserService를 상속받고, 이 중 사용자 정보를 가져오는 loadUser() 매서드를 구현합니다.

 

UserService.java

package com.koa.SpringOauth2Demo;

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.core.user.OAuth2User;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.Map;

@Service
public class UserService extends DefaultOAuth2UserService {

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest){
        OAuth2User oAuth2User = super.loadUser(userRequest); // 사용자 정보 가져옴
        Map<String, Object> attributes = oAuth2User.getAttributes();

        String userId = attributes.get("sub").toString();
        String email = attributes.get("email").toString();

        System.out.println("userId = " + userId);
        System.out.println("email = " + email);

        return new User(Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")), attributes, "email");
    }

}

 

loadUser 함수에서 return을 추가로 설명하자면

new SimpleGrantedAuthority("ROLE_USER")으로 사용자 권한을 설정하고, Collections.singleton()`으로 권한이 하나만 있는 불변의 set를 생성합니다.

 

SecurityConfig.java

package com.koa.SpringOauth2Demo;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final UserService userService;

    public SecurityConfig(UserService userService) {
        this.userService = userService;
    }
    
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        http
                .authorizeHttpRequests(auth->auth.anyRequest().authenticated())
                .oauth2Login(oauth2 -> oauth2
                        .userInfoEndpoint(userInfo -> userInfo
                                .userService(userService)) // OAuth2 로그인 후 사용자 정보 처리
                        .defaultSuccessUrl("/user/info") //성공 시 리다이렉트
                );

        return http.build();
    }

}

 

 

로그인 성공 시 리다이렉트할 페이지를 생성해줍니다.

 

UserController.java

package com.koa.SpringOauth2Demo;

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
@RequestMapping("/user")
public class UserController {
    
    @GetMapping("/info")
    public Map<String, Object> getUserInfo(@AuthenticationPrincipal User user){
        return user.getAttributes();
    }

}

 

 

 

 

완성~~

다음에 이어서 OAuth2 로그인 후 JWT 토큰 발급과 OAuth2 로그아웃 처리도 작성해보겠습니다.

 

'Server > Java, Spring' 카테고리의 다른 글