스프링부트+jsp로 배달사이트 만들기-34 구글아이디로 로그인

2021. 12. 22. 18:08스프링부트

1. https://console.cloud.google.com/projectselector2/home/dashboard 접속

 

Google Cloud Platform

하나의 계정으로 모든 Google 서비스를 Google Cloud Platform을 사용하려면 로그인하세요.

accounts.google.com

 

 

2. 프로젝트 선택

 

 

 

3. 새 프로젝트

 

 

4. 프로젝트 이름 아무거나 입력 후  만들기 클릭

 

 

 

5. OAuth 동의 화면

 

 

 

6.  외부 선택 후 만들기

 

7.  앱 이름 이메일 입력, 저장 후 계속

 

 

8. 사용자 인증 정보

 

9. 사용자 인증 정보 만들기 => OAuth 클라이언트 ID

 

 

10.  유형, 이름, 승인된 리디렉션 URI입력 후 만들기

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

Oauth를 사용하게되면 위 URI 고정

 

리디렉션 URI는 구글로그인이 완료가 되면 구글이 서버로 code를 돌려준다

이 code로 엑세스토큰을 요청한다

엑세스토큰을 받아서 사용자의 정보를 접근 할 수 있는 권한이 생긴다

 

http://localhost:8080/login/oauth2/code/google를 컨트롤러에 추가 할 필요없다 라이브러리가 처리해 주기 때문

 

 

 

11. 클라이언트ID와 비밀번호를 노출되지 않게 관리

 

 

 

 

pom.xml에 Oauth2 라이브러리를 추가합니다

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

 

Oauth2 라이브러리를 사용해 로그인 할 경우 요청 url은 /oauth2/authorization/로 고정입니다

 

 

application.properties에 생성한 클라이언트ID와 비밀번호를 적습니다

git에 푸시하기 전에 .gitignore파일에 application.properties를 추가해 application.properties는 푸시하지 않도록 합니다

 

SecurityConfig에 Oauth2 설정을 추가합니다

 

 

 

로그인 페이지에서 구글로그인 버튼 클릭

 

 

 

 

 

 

로그인 후 처리 작업을 할 클래스를 login패키지에 추가합니다

OauthUserService

@Service
public class OauthUserService extends DefaultOAuth2UserService {

	
	
	
}

 

SecurityConfig에서 OauthUserService를 실행할 수 있게 설정을 추가합니다

 

 

스프링 시큐리티 세션에는 Authentication객체만 들어갈 수 있습니다

Authentication 객체에는 UserDetails 객체와 OAuth2User가 들어 갈 수 있습니다

시큐리티 로그인을 하면 UserDetailsService의 loadUserByUsername() 메서드가 Authentication에 UserDetails클래스를 등록합니다

OAuth2 로그인을 하면 OauthUserService의 loadUser() 메서드가 Authentication에 OAuth2User클래스를 등록합니다

 

세션에 저장된 유저정보를 꺼낼 때 시큐리티 로그인했을땐 @AuthenticationPrincipal UserDetails user로 꺼내야 하고

OAth2로그인 시에는 @AuthenticationPrincipal OAuth2User user2로 꺼내야 하는데 둘을 구분 지어서 값을 꺼내기에는 불편함이 있습니다

 

이 때 UserDetails클래스와 OAuth2User의 타입을 맞춰주기 위해서 User클래스를 담은 LoginService클래스가 두 클래스를 implements합니다

 

 

 

LoginService

@Getter
@Setter
@ToString
public class LoginService implements UserDetails, OAuth2User {
	private User user;
	
	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		List<GrantedAuthority> roles = new ArrayList<>();
		roles.add(new GrantedAuthority() {
			@Override
			public String getAuthority() {
				return user.getRole();
			}
		});
		return roles;
	}

	@Override
	public String getPassword() {
		return user.getPassword();
	}

	@Override
	public String getUsername() {
		
		return user.getUsername();
	}

	@Override
	public boolean isAccountNonExpired() {
		return true;
	}

	@Override
	public boolean isAccountNonLocked() {
		return true;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		return true;
	}

	@Override
	public boolean isEnabled() {
		return true;
	}

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

	@Override
	public String getName() {
		return null;
	}

	

}

 

 

OauthUserService에서 사용자 정보를 받아올 메서드를 오버라이드 합니다

@Service
public class OauthUserService extends DefaultOAuth2UserService {

	@Autowired
	private SqlSession sql;
	
	@Override
	public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
		
		OAuth2User oauth2user = super.loadUser(userRequest);
		
		String provider = userRequest.getClientRegistration().getRegistrationId();
		
		String username = provider + "_" + oauth2user.getAttribute("sub"); 
		
		User user = sql.selectOne("user.login", username);
		
		if(user == null) {
			// 회원가입
			user = new User("아이디", "비번", "이메일", "닉네임", "전화번호");
			
		}
 		
		LoginService loginService = new LoginService();
		loginService.setUser(user);
		
		return loginService;
	}

	
	
}

String provider = userRequest.getClientRegistration().getRegistrationId(); == google

oauth2user.getAttribute("sub");  => 구글 계정의 유니크 값

provider + "_" + oauth2user.getAttribute("sub");로 구글아이디로 로그인한 사람의 username을 만듭니다

이 username으로 DB에서 해당 username이 있는지 확인하고 없다면 회원가입합니다

 

회원가입 코드를 추가합니다

@Autowired
private BCryptPasswordEncoder encodePwd;
if(user == null) {
	// 회원가입
	UUID uid = UUID.randomUUID();
	String password = encodePwd.encode(uid.toString());
	String email = oauth2user.getAttribute("email");
	String phone = oauth2user.getAttribute("phone") == null ? "" : oauth2user.getAttribute("phone");
	
	Join join = new Join();
	join.setUsername(username);
	join.setPassword(password);
	join.setEmail(email);
	join.setNickname(username);
	join.setPhone(phone);
	
	userDAO.join(join);
	
	user = sql.selectOne("user.login", username);
}

비밀번호는 랜덤으로 설정하고 

이메일을 구글계정의 이메일을 사용합니다

전화번호는 구글계정의 전화번호가 있다면 사용하고 없다면 빈값으로 설정합니다