今度にはoauth2を使用してGoogleLOGINを具現します。
まず、google api consoleで行きます。
そしてoauthの同意とUSERの認証を作ります。
そして、projectのmaven依存性を追加します。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
そして、
spring.security.oauth2.client.registration.google.client-id
とspring.security.oauth2.client.registration.google.client-secret
spring.security.oauth2.client.registration.google.scope=email,profile
にGoogleclientIDとpasswordを書きます。
そして、configを追加します。
.and()
.oauth2Login()
.loginPage("/loginform")
.failureUrl("/loginform")
.userInfoEndpoint()
.userService(principalOauth2UserService)
そして、google loginをためにServiceを具現します。
package com.rbwsn.oauth;
import com.rbwsn.auth.SecurityDetails;
import com.rbwsn.constant.Role;
import com.rbwsn.controller.IndexController;
import com.rbwsn.entity.User;
import com.rbwsn.repository.UserRepository;
import com.rbwsn.service.UserService;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.RequestDispatcher;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
@Service
@Transactional
public class PrincipalOauth2UserService extends DefaultOAuth2UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private PasswordEncoder passwordEncoder;
@SneakyThrows
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2User oAuth2User = super.loadUser(userRequest);
String provider = userRequest.getClientRegistration().getClientId();
String providerId = oAuth2User.getAttribute("sub");
String email = oAuth2User.getAttribute("email");
String name = oAuth2User.getAttribute("name") + providerId;
String password = passwordEncoder.encode("google1234");
User user = userRepository.findByEmail(email);
if (user == null) {
user = User.builder()
.username(name)
.provider(provider)
.password(password)
.email(email)
.role(Role.ROLE_USER)
.provider_id(providerId)
.build();
userRepository.save(user);
}else{
throw new IllegalStateException("aaa");
}
return new SecurityDetails(user, oAuth2User.getAttributes());
}
}
password 와 DB저장을 위해 레파지토리와 패스워드 인코더를 받습니다.
AUtowired 받습니다.
그리고 Security에서는 세션의 정보로 OAuth2User 그리고 UserDetails만 받기 때문에
만약에 비교검사를해서 user정보를 SecurityDetails에 넘겨 주게 됩니다.
package com.rbwsn.auth;
//LOGINが終わったらSESSIONを作ります。
import com.rbwsn.entity.User;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.core.user.OAuth2User;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
@Data
public class SecurityDetails implements UserDetails, OAuth2User {
User user;
private Map<String,Object> attributes;
public SecurityDetails(User user){
this.user=user;
}
public SecurityDetails(User user, Map<String,Object> attributes){
this.user=user;
this.attributes = attributes;
}
//権限をReturn
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> collection = new ArrayList<>();
collection.add(new GrantedAuthority() {
@Override
public String getAuthority() {
return user.getRole().toString();
}
});
return collection;
}
@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;
}
@Override
public <A> A getAttribute(String name) {
return null;
}
@Override
public Map<String, Object> getAttributes() {
return attributes;
}
@Override
public String getName() {
return null;
}
}
ここではGoogleの情報はMap<String,Object> 形式ですから、新しい生成します。
Controllerには
@GetMapping("/user")
public @ResponseBody String user(@AuthenticationPrincipal SecurityDetails securityDetails){
System.out.println("prin:"+ securityDetails.getUser().toString());
return "user";
}
@AuthenticationPrincipalを私が生成したCLASSにDIします。