티스토리 뷰
자세한 코드: Github
구글, Github, 네이버 등과 같은 소셜 로그인 기능을 사용하는 경우를 발견할 수 있다.
로그인 기능을 직접 구현하면 다음과 같은 기능이 필요하다.
- 로그인 시 보안
- 회원가입 시 본인 인증
- 비밀번호 찾기
- 비밀번호 변경
- 회원정보 변경
OAuth 로그인을 사용하면 위의 기능들을 직접구현 하는 것을 대체할 수 있다는 장점이 있다.
Google Cloud Platfrom 설정
Google Cloud Platform에 접속하여 상단 바에 있는 프로젝트 선택 탭을 클릭한다.
오른쪽 위의 새 프로젝트를 클릭한다.
프로젝트 이름을 입력하고 프로젝트를 만든다.
상단바에 왼쪽에 메뉴에 들어가서 API 및 서비스 메뉴로 이동한다.
사용자 인증 정보 메뉴에 들어간 다음, [+ 사용자 인증 정보 만들기] 버튼을 클릭한다.
[OAuth 클라이언트 ID]를 클릭한다.
동의 화면 구성을 클릭한다.
내부는 조직 내 사용자만, 외부는 Google 계정이 있는 모든 사용자가 사용할 수 있다.
User Type은 외부로 설정해서 만든다.
위와 같은 절차를 진행한다.
앱 정보에 앱 이름을 이볅하고 그 외의 필요한 정보들을 입력한다.
차례대로 진행하면 된다.
사용자 인증 정보 항목에 들어가서 [+ 사용자 인증 정보 만들기]에서 [OAuth 클라이언트 ID]를 클릭한다.
제작한 애플리케이션의 유형을 선택한다.
승인된 리디렉션 URI에 입력을 하고 [만들기]를 클릭한다.
승인된 리디렉션 URI란?
- 서비스에서 파라미터로 인증 정보를 주었을 때 인증이 성공하면 구글에서 리다이렉트할 URL
- 스프링 부트 2 버전의 시큐리티에서는 기본적으로 {도메인}/login/oauth2/code/{소셜서비스코드}로 리다이렉트 URL을 지원
- 시큐리티에서 이미 구현해 놓은 상태이기 때문에 사용자가 별도로 URL을 지원하는 Controller를 만들 필요가 없음
- 위의 이미지에서는 개발 단계이기 때문에 localhost:8080을 사용
- AWS 서버에 배포할 시 localhost 외에 추가로 주소를 추가해야 함
만들기를 하면 위와 같은 항목을 볼 수 있다.
클라이언트 ID와 클라이언트 보안 비밀 코드를 프로젝트에서 설정
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
= 오른쪽에 발급 받은 클라이언트ID와 클라이언트 보안 비밀을 입력한다.
scope=profile,email
- 기본값이 openid, profile, email
- 위의 코드에서 openid가 없는 이유는 openid가 있다면 Open Id Profider로 인식하기 때문
- OpenId가 있다면 OpenId Provider인 서비스(구글)와 그렇지 않은 서비스(네이버/카카오 등)으로 나눠서 OAuth2Service를 만들어야 함
- profile과 email만 등록함으로써 하나의 OAuth2Service를 사용
스프링부트에서 properties의 이름을 application-xxx.properties로 만들면 xxx라는 이름의 profile이 생성되고 이를 통해 관리할 수 있다. profile=xxx라는 식으로 호출하면 해당 properties의 설정을 가져올 수 있다.
spring.profiles.include=oauth
application.properties에 위의 내용을 추가하면 application-oauth.properties의 설정값을 사용할 수 있다.
구글 로그인을 위한 클라이언트 ID와 클라이언트 보안 비밀은 개인 정보이다. 이 정보들이 노출되면 개인정보가 유출되는 문제가 발생할 수 있다. .gitinore에 해당 파일을 등록하여 올라가는 것을 방지해야 한다.
vi .gitignore을 하여 application-oauth.properties 파일을 등록한다.
git status를 사용해서 파일이 보이지 않으면 성공이다.
💡 .gitignore이 적용되지 않는 경우
git rm -r --cached .
git add .
git commit -m "fixed untracked files"
위의 세 명령어로 캐시를 삭제하면 해결된다.
@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
- 숫자로 저장이 되면 값이 무슨 코드를 의미하는지 알 수 없음
public enum Role {
GUEST("ROLE_GUEST", "손님");
USER("ROLE_USER", "일반 사용자");
private final String key;
private final String title;
}
권한을 관리한는 Enum 클래스이다.
스프링 시큐리티에서는 권한 코드의 앞에 ROLE_이 있어야만 한다.
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByEmail(String email);
}
User의 CRUD를 담당하는 UserRepository이다.
Optional<User> findByEmail(String email);
- 소셜 로그인으로 반환되는 값 중 email을 통해 이미 생성된 사용자인지 처음 가입하는 사용자인지 판단하는 메소드
// build.gradle 파일
// 라이브러리들을 받아올 원격 저장소 결정
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.projectlombok:lombok')
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('com.h2database:h2')
compile('org.springframework.boot:spring-boot-starter-mustache')
compile('org.springframework.boot:spring-boot-starter-oauth2-client') // 시큐리티 관련 의존성
testCompile('org.springframework.boot:spring-boot-starter-test')
}
build.gradle에 dependencies에 아래에 있는 시큐리티 관련 의존성을 추가한다.
spring-boot-starter-oauth2-client
- 클라이언트 입장에서 소셜 기능 구현 시 필요한 의존성
- spring-security-oauth2-client와 spring-security-oauth2-jose를 기본으로 관리
💡 의존성을 추가하고 나서는 항상 새로고침 버튼을 누르도록 하자! 이것 때문에 문제를 찾느라 꽤 오래 걸렸다.
RequiredArgsConstructor
@EnableWebSecurity // Spring Security 설정들을 활정화
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final CustomOAuth2UserService customOAuth2UserService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable().headers().frameOptions().disable() // h2-console 화면을 사용하기 위한 설정
.and()
.authorizeRequests() // URL별 권한 관리를 설정하는 옵션의 시작점
.antMatchers("/", "/css/**", "/images/**", "/js/**", "/h2-console/**").permitAll() // 전체 열람 권한
.antMatchers("/api/v1/**").hasRole(Role.USER.name()) // USER 권한을 가진 사람만
.anyRequest().authenticated() // anyReQuest(): 설정된 값들 이외 나머지 URL, authenticated
.and()
.logout() // 로그아웃 시
.logoutSuccessUrl("/") /// 로 이동
.and()
.oauth2Login() // oauth2 로그인
.userInfoEndpoint() // 로그인 이후 사용자 정보를 가져올 때 설정
.userService(customOAuth2UserService); // 로그인 성공 시 진행할 인터페이스 구현체 등록
}
}
@EnableWebSecurity
- Spring Security 활성화
authorizeRequests()
- antMatchers 옵션을 사용하기 위한 코드
antMatchers
- URL, HTTP 메소드 등으로 권한 관리 대상 지정
- "/"은 모두 허용
- "/api/v1/**"는 USER 권한을 가지면 허용
anyRequest
- 나머지 URL 처리
authenticated
- 인증된 사용자들만
logout().logoutSuccessUrl("/")
- 로그아웃시 이동
- Total
- Today
- Yesterday
- solidity
- git
- pm.expect
- github
- pm.test
- 네이버 2022 공채
- Squash and merge
- python3
- string
- 2차 인터뷰
- go 특징
- java
- 1차 인터뷰
- 확장 함수
- hashcode
- DGS Framework
- graphql
- squash merge
- downTo
- Kotlin In Action
- postman tests
- 주생성자
- 코딩테스트
- Python
- 코틀린
- mysql
- Kotlin
- postman collection
- postman
- Basic Type
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |