2021. 12. 22. 18:08ㆍ스프링부트
1. https://console.cloud.google.com/projectselector2/home/dashboard 접속
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);
}
비밀번호는 랜덤으로 설정하고
이메일을 구글계정의 이메일을 사용합니다
전화번호는 구글계정의 전화번호가 있다면 사용하고 없다면 빈값으로 설정합니다
'스프링부트' 카테고리의 다른 글
스프링부트+jsp로 배달사이트 만들기-36 카카오아이디로 로그인 (0) | 2021.12.23 |
---|---|
스프링부트+jsp로 배달사이트 만들기-35 네이버아이디로 로그인 (0) | 2021.12.23 |
스프링부트+jsp로 배달사이트 만들기-33 내 포인트, 리뷰 확인 (0) | 2021.12.22 |
스프링부트+jsp로 배달사이트 만들기-32 매출 관리 (0) | 2021.12.20 |
스프링부트+jsp로 배달사이트 만들기-31 웹소켓으로 실시간 주문받기 (0) | 2021.12.17 |