Spring Security 정리

형석이의 성장일기·2024년 4월 3일
0

Spring Security

목록 보기
3/6
post-thumbnail

Sprign Security 란

  • Spring 애플리케이션의 인증 및 인가를 필터를 사용해 담당하는 프레임워크

특징

  • Filter 를 기반으로 동작함
    • Filter 를 빈 객체로 등록 가능함
  • 필터를 정상적으로 거친 요청의 경우 모든 메서드에서 UserDetail 을 통해 유저 정보를 가져올 수 있음

용어

  • 접근 주체 (Principal) : 요청을 보낸 유저
  • 인증 (Authenticate) : 로그인을 시도한 유저 확인
  • 인가 (Authorize) : 현재 요청을 보낸 유저가 해당 요청을 수행하기에 적합한 권한을 가지고 있는지 확인

Spring Security 구조 & 흐름

  1. 유저에게 Form 을 통해 로그인을 시도하는 HTTP 요청이 들어옴
  2. AuthenticationFilter 가 요청을 인터셉트해서 AhtenticationManager (구현체는 ProviderManager) 에게 인증용 토큰인 UsernamePasswordAuthenticationToken 을 넘겨줌

  • principal 에 유저 정보를 담고 있음 (내가 구현한 코드에선 유저 이메일)
  1. AhtenticationManager 가 UserDetatilService 에게 UsernamePasswordAuthenticationToken 을 전달해 DB에 등록되어 있는 유저인지 확인

  2. 만약 등록된 유저라면 해당 정보를 바탕으로 Authentication 객체 (UserDetails) 생성

    • 여기서 사용한 유저 정보는 유저 이메일, 패스워드, 역할
    @Service
    @RequiredArgsConstructor
    public class UserDetailsServiceImpl implements UserDetailsService {
    
        private final UserRepository userRepository;
    
        // username (email) 이 DB에 존재하는지 확인
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            // 시큐리티 세션에 유저 정보 저장
            return userRepository.findUserByEmail(username)
                    .map(this::createUserDetails)
                    .orElseThrow(() -> new UsernameNotFoundException("사용자가 존재하지 않습니다."));
        }
    
        // DB 에 User 값이 존재한다면 UserDetails 객체로 만들어서 리턴
        private UserDetails createUserDetails(User user) {
            GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(user.getAuthority().toString());
    
            return new org.springframework.security.core.userdetails.User(
                    user.getEmail(),
                    user.getPassword(),
                    Collections.singleton(grantedAuthority)
            );
        }		
    }
  3. AuthenticationProvider 는 UserDetails 객체를 전달 받은 이후 실제 유저가 로그인을 위해 입력한 정보와 UserDetails 객체를 가지고 인증을 시도

  4. 인증이 완료되면 유저 정보를 가진 Authentication 객체를 SercurityContextHolder 에 저장하여 Spring 애플리케이션에서 사용함

Security Context Holder

  • Spring Security 는 유저의 정보에 대한 모든 인증이 통과되고, Authentication 객체까지 생성되면 Principal, Credentials, Authorities 를 담고있는 Authentication 객체Security Context 에 담고, 이를 Security Context Holder 에 보관함
  • Security Context HolderTread Local 을 사용함
    • 이유는 한 쓰레드에서 사용자 정보를 설정하면 이 Authentication 객체는 해당 쓰레드 내에서 언제든지 Authentication 객체를 사용해 유저 정보를 조회할 수 있다는 것

Security Context Holder, @AuthenticationPrincipal

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/user")
public class UserController {

    private final AuthService authService;
		
		...
		
    @GetMapping("/test")
    public ResponseEntity<String> accessTokenTest(@AuthenticationPrincipal UserDetails userDetails) {
        return ResponseEntity.status(HttpStatus.OK).body(userDetails.getUsername());
    }
}
  • 위의 코드처럼 @AuthenticationPrincipal 어노테이션을 사용해 인증을 거친 유저 정보를 모든 메서드에서 사용할 수 있음
  • 이 정보는 Security Context Holder 에서 가져온 정보임
  • 하지만 로그인, 회원가입, Access Token 재발급 코드 같이 필터에서 제외된 요청은 사용하면 안됨!
profile
이사중 .. -> https://gudtjr2949.tistory.com/

0개의 댓글

관련 채용 정보