오늘은 회원가입, 로그인, 권한 설정까지 끝냈다!.!
드디어 OAuth를 건드릴 수 있음 후후,, 저녁 먹고 세팅만 해놔야지

// SecurityConfig.java
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
비밀번호 암호화를 위해서 SecurityConfig에 BCryptPasswordEncoder Bean을 생성해줬다.
(일단 예제에서 서비스를 따로 안 만들고 컨트롤러에서 구현해서 따라했는데 지금 보니까 나중에 서비스로 다시 빼야겠다.)
// IndexController.java
@Autowired
private UserRepository userRepository;
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@PostMapping("/join") // 회원가입 요청
public String join(User user){
user.setRole("ROLE_USER");
// 패스워드 암호화해서 유저에 다시 세팅
String rawPassword = user.getPassword();
String encPassword = bCryptPasswordEncoder.encode(rawPassword);
user.setPassword(encPassword);
// 유저 DB에 저장
userRepository.save(user);
return "redirect:/loginForm";
}
너무나도 간단하게 회원가입 끝..아직 기본이니까요😬🙌
아무튼 bCryptPasswordEncoder 이용해서 비밀번호 암호화 후에 유저에 다시 세팅해서 DB에 저장해주기!
SecurityConfig에 추가된 부분 있는데
.formLogin(formLogin -> // 로그인 설정
formLogin.loginPage("/loginForm")
// 권한 없을 경우, 로그인 페이지로
.loginProcessingUrl("/login")
// /login 주소가 호출되면 시큐리티가 낚아채서 대신 로그인 진행
.defaultSuccessUrl("/")
// 로그인 페이지로 접속했을 경우, default 페이지로 -> 아닌 경우 요청했던 페이지로 감
)
이 부분으로 로그인 요청하면 시큐리티가 로그인 진행할 수 있게 하고
// Spring Security가 요청을 가로채서 PrincipalDetailsService의 loadUserByUsername() 호출
@Service
public class PrincipalDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
// security session(내부 Authentication(내부 UserDetails))
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User userEntity = userRepository.findByUsername(username);
if(userEntity != null){
return new PrincipalDetails(userEntity);
}
return null;
}
}
public class PrincipalDetails implements UserDetails {
private User user;
public PrincipalDetails(User user){
this.user = user;
}
// 해당 유저의 권한을 리턴하는 곳
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> collection = new ArrayList<>();
collection.add(new GrantedAuthority() {
@Override
public String getAuthority() {
return user.getRole();
}
});
return collection;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
...
라고 코드는 간단하지만,,,그래서 과정이 정확히 어떻게 되는건데 싶어서
SpringSecurity를 이용한 회원 로그인 구현과 동작 원리 정리
위처럼 너무 좋은 링크 발견과,,,지피티한테 물어봤다. 근데 링크가 너무 좋음ㅎㅎ
SecurityContext에 인증 정보를 저장사용자의 로그인 요청:
/login URL로 POST 요청을 보냅니다.인증 필터가 요청을 가로챔:
UsernamePasswordAuthenticationFilter가 /login 요청을 가로채고, 사용자 이름과 비밀번호를 추출합니다.Authentication 객체 생성:
UsernamePasswordAuthenticationFilter는 추출한 사용자 이름과 비밀번호로 UsernamePasswordAuthenticationToken 객체를 생성합니다. 이 객체는 인증되지 않은 상태입니다.AuthenticationManager에 전달:
UsernamePasswordAuthenticationToken 객체는 AuthenticationManager로 전달됩니다. Spring Security의 기본 구현에서는 ProviderManager가 AuthenticationManager를 구현합니다.AuthenticationProvider 사용:
ProviderManager는 하나 이상의 AuthenticationProvider를 가지고 있으며, 각각은 특정 유형의 인증을 처리합니다. 기본 설정에서는 DaoAuthenticationProvider가 주로 사용됩니다.UserDetailsService 호출:
DaoAuthenticationProvider는 UserDetailsService를 사용하여 사용자 정보를 로드합니다. 이 과정에서 PrincipalDetailsService가 호출되어 데이터베이스에서 사용자 정보를 가져오고, PrincipalDetails 객체를 반환합니다.비밀번호 검증:
DaoAuthenticationProvider는 UserDetails에서 반환된 사용자 정보(PrincipalDetails)와 입력된 비밀번호를 비교하여 인증을 진행합니다. 비밀번호가 일치하면 인증이 성공한 것으로 간주합니다.인증된 Authentication 객체 생성:
DaoAuthenticationProvider는 인증된 UsernamePasswordAuthenticationToken 객체를 생성합니다. 이 객체에는 인증된 사용자 정보(PrincipalDetails)와 권한 정보가 포함됩니다.SecurityContext에 저장:
Authentication 객체는 SecurityContextHolder를 통해 SecurityContext에 저장됩니다. 이로 인해 현재 사용자의 인증 상태와 정보를 애플리케이션의 모든 부분에서 참조할 수 있게 됩니다.인증 성공 후 처리:
UserDetails:
PrincipalDetails 클래스가 이를 구현하여 사용자 정보를 제공합니다.UserDetailsService:
PrincipalDetailsService 클래스가 이를 구현하여 데이터베이스에서 사용자 정보를 가져옵니다.Authentication:
UsernamePasswordAuthenticationToken 클래스가 이를 구현하여 사용자 이름과 비밀번호를 포함합니다.AuthenticationProvider:
DaoAuthenticationProvider 클래스가 이를 구현하여 UserDetailsService를 사용하여 사용자 정보를 검증합니다.SecurityContext:
SecurityContextHolder를 통해 접근할 수 있습니다.