본문 바로가기
Spring/Spring Security

[Spring Security] UserDetailsService

by seoyamin 2023. 2. 1.

[참고]  https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0/dashboard

 

[무료] 스프링부트 시큐리티 & JWT 강의 - 인프런 | 강의

스프링부트 시큐리티에 대한 개념이 잡힙니다., - 강의 소개 | 인프런...

www.inflearn.com

 

0. 전반적 흐름

오늘은 UserDetails 타입의 유저 정보 객체를 저장하는 Authentication 객체를 알아볼 것이다.

Authentication은 UseDetailsService를 implements한 PrincipalDetailsService를 통해 만들 수 있다.

 

 

 

1. PrincipalDetailsService 뜯어보기

package com.cos.security1.config.auth;

import com.cos.security1.model.User;
import com.cos.security1.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

@Service
public class PrincipalDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    // 여기서 Authentication 내부에 UserDetails 저장되고, 이 Authentication이 ContextHolder에 저장됨
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User userEntity = userRepository.findByUsername(username);
        if(userEntity != null) {
            return new PrincipalDetails(userEntity);
        }
        return null;
    }
}

 

SecurityConfigloginProcessingUrl("/login")으로 로그인 요청이 오면 자동으로 UserDetailsService 타입으로 IoC 되어있는 loadUserByUsername 함수가 실행된다.

 

 

이때, String username은 반드시 "/login"에서 username이라는 변수명으로 요청을 보내줘야 한다.

만약, 내가 "/login"에서 다른 변수명을 (ex. username2) 사용해서 로그인 요청을 보내고 싶다면 SecurityConfig에서 usernameParameter("username2") 설정을 추가해줘야 한다.

 

// SecurityConfig.java

http.authorizeRequests()
                .antMatchers("/user/**").authenticated()
                .antMatchers("/manager/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_MANAGER')")
                .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
                .anyRequest().permitAll()

                .and()
                .formLogin()
                .loginPage("/loginForm")
                .usernameParameter("username2")     // 추가
                .loginProcessingUrl("/login")   
                .defaultSuccessUrl("/");