특징
용어
UsernamePasswordAuthenticationToken
을 넘겨줌
principal
에 유저 정보를 담고 있음 (내가 구현한 코드에선 유저 이메일)AhtenticationManager 가 UserDetatilService 에게 UsernamePasswordAuthenticationToken
을 전달해 DB에 등록되어 있는 유저인지 확인
만약 등록된 유저라면 해당 정보를 바탕으로 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)
);
}
}
AuthenticationProvider
는 UserDetails 객체를 전달 받은 이후 실제 유저가 로그인을 위해 입력한 정보와 UserDetails 객체를 가지고 인증을 시도
인증이 완료되면 유저 정보를 가진 Authentication
객체를 SercurityContextHolder 에 저장하여 Spring 애플리케이션에서 사용함
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
어노테이션을 사용해 인증을 거친 유저 정보를 모든 메서드에서 사용할 수 있음로그인, 회원가입, Access Token 재발급 코드
같이 필터에서 제외된 요청은 사용하면 안됨!