728x90
1 . 환경설정
POM.XML 을 다음과 같이 설정해줍니다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
application.yml에 다음과 같이 설정한다.
oauth2:
client:
registration:
facebook:
client-id: facebook에서 받은 id
client-secret: facebook에서 받은 시크릿키
scope:
- public_profile # 회사마다 다름
- email
2. SecurtyConfig.java
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/","/user/**","/image/**","/subscribe/**","/comment/**","/api/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin()//위에있는 url말고 다른곳에 들어갈 경우 loginPage로 redirect시킴
.loginPage("/auth/signin")//get
.loginProcessingUrl("/auth/signin")//post-> 스프링 시큐리티가 로그인 프로세스진행
.defaultSuccessUrl("/")
.and()
.oauth2Login()// form 로그인을 포함하여 oauth2 로그인도 할거임
.userInfoEndpoint()//oauth2 로그인을하게되면, 바로 회원정보를 돌려줘
.userService(oauth2DetailsService);
}
3. Oauth2DetailsServce.java
@RequiredArgsConstructor
@Service
public class Oauth2DetailsService extends DefaultOAuth2UserService {
private final UserRepository userRepository;
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2User oAuth2User= super.loadUser(userRequest); // 응답한 userRequest정보를 파싱해서줌
Map<String,Object> userInfo=oAuth2User.getAttributes();
String name= (String) userInfo.get("name");
String email= (String) userInfo.get("email");
String username="facebook_"+(String) userInfo.get("id");
String password=new BCryptPasswordEncoder().encode(UUID.randomUUID().toString());
User userEntity = userRepository.findByUsername(username);
if(userEntity==null) {//페이스북 최초 로그인
User user=User.builder()
.username(username)
.password(password)
.name(name)
.email(email)
.role("ROLE_USER")
.build();
return new PrincipalDetails(userRepository.save(user),oAuth2User.getAttributes());
}else{ //회원가입이 되어 있다면
return new PrincipalDetails(userEntity,oAuth2User.getAttributes()); //페이스북 로그인인지 일반로그인
}
}
}
4. PrincipalDetails.java
@Data
@RequiredArgsConstructor
public class PrincipalDetails implements UserDetails, OAuth2User {
private User user;
private Map<String,Object> attributes;
public PrincipalDetails(User user) {
this.user = user;
}
public PrincipalDetails(User user,Map<String,Object> attributes) {
this.user = user;
this.attributes=attributes;
}
//권한: 한개가 아닐수있음(3개일수도 ?)
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> collection=new ArrayList<>();
collection.add(()->{
return user.getRole();
});
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;
}
// =================oauth2=====================
@Override
public Map<String, Object> getAttributes() {
return attributes; // {id:123123123,name:"김민우", email:"ㅁㄴㅇㅁ@nvaer.com}
}
@Override
public String getName() {
return (String) attributes.get("name");
}
}
5. PrincipalDetailsService.java
@RequiredArgsConstructor
@Service
public class PrincipalDetailsService implements UserDetailsService {
private final UserRepository userRepository;
//패스워드는 알아서 체킹하니까 신경쓸 필요없다
//리턴이 잘되면 내부적으로 자동으로 세션을 만든다.
//UserDetails 타입을 세션으로 만든다.
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User userEntity = userRepository.findByUsername(username);
if(userEntity==null){
return null;
}else{
return new PrincipalDetails(userEntity);
}
}
}
6. 페이스북 로그인 동작과정
1. 클라이언트가 Facebook 로그인 버튼을 클릭한다.
2. FaceBook Login Form 으로 이동한다.
3. 클라이언트가 페이스북계정의 아이디와 비밀번호로 로그인을 시도한다.
4. 웹페이지 개발자가 만든 앱리스트가 해당하는 페이스북사이트에 있는지 확인을 한다.
(yml 에서 등록한 클라이언트 아이디와 시크릿키로 확인을한다)
5. 페이스북 DB테이블에 해당하는 클라이언트의 ID와 비밀번호가 있는지 확인한다.
6. DB에 해당하는 유저의 데이터가 존재하면 인증코드를 돌려준다
7.인증코드로 AccessToken을 요청한다 (AccessToken 으로 유저의 정보를 가져올수있음)
8. Accesstoken으로 가져온 사용자의정보를 활용하여 회원가입을 강제로 시킨다.
oauth2 client를 사용하게되면 6 7 번을 자동으로 수행해주기때문에 우리는
사용자의 정보를 가져와 회원가입을 시켜주는 로직을 수행하면된다.
Sercurity 동작과정을 모르는사람들위해 해당하는 사진을 넣어보겠다.
728x90
'Spring Security' 카테고리의 다른 글
로그인 실패시 Failure Handler (0) | 2023.02.20 |
---|---|
Spring Security CSRF (0) | 2023.02.02 |