SpringSecurity - 회원가입, 로그인, 권한 설정

hsso_o·2024년 7월 12일
0

스터디

목록 보기
21/44

오늘은 회원가입, 로그인, 권한 설정까지 끝냈다!.!
드디어 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;
    }
}
  • PrincipalDetailsService는 UserRepository를 사용하여 사용자 정보를 데이터베이스에서 조회
  • 조회된 사용자 정보로 PrincipalDetails 객체를 생성하여 반환
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();
    }
    
    ...
  • UserDetails 인터페이스를 구현하여 사용자 정보와 권한 제공

라고 코드는 간단하지만,,,그래서 과정이 정확히 어떻게 되는건데 싶어서

SpringSecurity를 이용한 회원 로그인 구현과 동작 원리 정리
위처럼 너무 좋은 링크 발견과,,,지피티한테 물어봤다. 근데 링크가 너무 좋음ㅎㅎ

아래는 지피티가 알려준 내용🤖

Spring Security 인증 과정

  • Spring Security는 인증 절차를 통해 사용자를 검증하고, 성공 시 SecurityContext에 인증 정보를 저장

인증 과정

  1. 사용자의 로그인 요청:

    • 사용자가 로그인 폼을 통해 사용자 이름(username)과 비밀번호(password)를 입력하고, /login URL로 POST 요청을 보냅니다.
  2. 인증 필터가 요청을 가로챔:

    • UsernamePasswordAuthenticationFilter/login 요청을 가로채고, 사용자 이름과 비밀번호를 추출합니다.
  3. Authentication 객체 생성:

    • UsernamePasswordAuthenticationFilter는 추출한 사용자 이름과 비밀번호로 UsernamePasswordAuthenticationToken 객체를 생성합니다. 이 객체는 인증되지 않은 상태입니다.
  4. AuthenticationManager에 전달:

    • 생성된 UsernamePasswordAuthenticationToken 객체는 AuthenticationManager로 전달됩니다. Spring Security의 기본 구현에서는 ProviderManagerAuthenticationManager를 구현합니다.
  5. AuthenticationProvider 사용:

    • ProviderManager는 하나 이상의 AuthenticationProvider를 가지고 있으며, 각각은 특정 유형의 인증을 처리합니다. 기본 설정에서는 DaoAuthenticationProvider가 주로 사용됩니다.
  6. UserDetailsService 호출:

    • DaoAuthenticationProviderUserDetailsService를 사용하여 사용자 정보를 로드합니다. 이 과정에서 PrincipalDetailsService가 호출되어 데이터베이스에서 사용자 정보를 가져오고, PrincipalDetails 객체를 반환합니다.
  7. 비밀번호 검증:

    • DaoAuthenticationProviderUserDetails에서 반환된 사용자 정보(PrincipalDetails)와 입력된 비밀번호를 비교하여 인증을 진행합니다. 비밀번호가 일치하면 인증이 성공한 것으로 간주합니다.
  8. 인증된 Authentication 객체 생성:

    • 인증이 성공하면 DaoAuthenticationProvider는 인증된 UsernamePasswordAuthenticationToken 객체를 생성합니다. 이 객체에는 인증된 사용자 정보(PrincipalDetails)와 권한 정보가 포함됩니다.
  9. SecurityContext에 저장:

    • 인증된 Authentication 객체는 SecurityContextHolder를 통해 SecurityContext에 저장됩니다. 이로 인해 현재 사용자의 인증 상태와 정보를 애플리케이션의 모든 부분에서 참조할 수 있게 됩니다.
  10. 인증 성공 후 처리:

  • 인증이 성공하면, 사용자는 요청한 자원에 접근할 수 있습니다. 기본적으로는 로그인 후 지정된 페이지로 리다이렉트됩니다.

주요 클래스 및 인터페이스

  • UserDetails:

    • 사용자 정보를 제공하는 인터페이스입니다. PrincipalDetails 클래스가 이를 구현하여 사용자 정보를 제공합니다.
  • UserDetailsService:

    • 사용자 정보를 로드하는 인터페이스입니다. PrincipalDetailsService 클래스가 이를 구현하여 데이터베이스에서 사용자 정보를 가져옵니다.
  • Authentication:

    • 인증 정보를 나타내는 인터페이스입니다. UsernamePasswordAuthenticationToken 클래스가 이를 구현하여 사용자 이름과 비밀번호를 포함합니다.
  • AuthenticationProvider:

    • 인증을 처리하는 인터페이스입니다. DaoAuthenticationProvider 클래스가 이를 구현하여 UserDetailsService를 사용하여 사용자 정보를 검증합니다.
  • SecurityContext:

    • 현재 인증된 사용자 정보를 저장하는 인터페이스입니다. SecurityContextHolder를 통해 접근할 수 있습니다.
profile
아뇨 소혠데요-

0개의 댓글