Spring Security 란?
Spring Security는 일반적인 공격에 대한 인증 , 권한 부여 및 보호 기능을 제공하는 프레임워크이다
Filter Chain
FilterChainProxy 를 통해 상세 로직을 구현하고 있다.
Spring Security 필터 구조 는 아래와 같다.
UsernamePasswordAuthenticationFilter -> UsernamePasswordAuthenticationFilter -> AuthentucationManager
Security 대신 Filter 처리 해보기
@Slf4j(topic = "AuthFilter")
@RequiredArgsConstructor
@Component
@Order(2)
public class AuthFilter implements Filter {
private final UserRepository userRepository;
private final JwtUtil jwtUtil;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String url = httpServletRequest.getRequestURI();
if (StringUtils.hasText(url) &&
(url.startsWith("/api/user") || url.startsWith("/css") || url.startsWith("/js"))
) {
// 회원가입, 로그인 관련 API 는 인증 필요없이 요청 진행
chain.doFilter(request, response); // 다음 Filter 로 이동
} else {
// 나머지 API 요청은 인증 처리 진행
// 토큰 확인
String tokenValue = jwtUtil.getTokenFromRequest(httpServletRequest);
if (StringUtils.hasText(tokenValue)) { // 토큰이 존재하면 검증 시작
// JWT 토큰 substring
String token = jwtUtil.substringToken(tokenValue);
// 토큰 검증
if (!jwtUtil.validateToken(token)) {
throw new IllegalArgumentException("Token Error");
}
// 토큰에서 사용자 정보 가져오기
Claims info = jwtUtil.getUserInfoFromToken(token);
User user = userRepository.findByUsername(info.getSubject()).orElseThrow(() ->
new NullPointerException("Not Found User")
);
request.setAttribute("user", user);
chain.doFilter(request, response); // 다음 Filter 로 이동
} else {
throw new IllegalArgumentException("Not Found Token");
}
}
}
}
이런식으로 쓰긴 하지만 Security 는 좀더 편리하게 url 를 requestMatches 를 통해 관리 할수 있게 해주고 실패할경우와
성공할경우도 Handler 를 통해 더 편리하게 사용이 가능하다,
AuthentucationManager -> UserDetailsService -> AuthentucationManager
UserDetailsService
- UserDetailsService는 username/password 인증방식을 사용할 때 사용자를 조회하고 검증한 후 UserDetails를 반환합니다. Custom하여 Bean으로 등록 후 사용 가능합니다.
UserDetails
- 검증된 UserDetails는 UsernamePasswordAuthenticationToken 타입의 Authentication를 만들 때 사용되며 해당 인증객체는 SecurityContextHolder에 세팅됩니다. Custom하여 사용가능합니다.
로그인 구조
Authentication Manager -> UserDetailsService ( DB 조회 ) -> UserDetils (로 반환) -> Authentication Manager
UserDetailsService : DB 에서 해당 entity 있는지 확인 후 있다면 해당 entity 를 Authentication Manager 에게 반환후
Authentication Manager 에서 id, password 비교 처리
SecurityContextHolder ?
- SecurityContext는 인증이 완료된 사용자의 상세 정보(Authentication)를 저장합니다.
- 안에 SecurityContext 안에 Authentication 안에 Principal, Credentials, Authorities 가 담긴다.
- SecurityContextHolder는 소멸은 request 요청이 끝난 후에 소멸한다.
Authentication
- 현재 인증된 사용자를 나타내며 SecurityContext에서 가져올 수 있습니다.
- principal : 사용자를 식별합니다.
- Username/Password 방식으로 인증할 때 일반적으로 UserDetails 인스턴스입니다.
- credentials : 주로 비밀번호, 대부분 사용자 인증에 사용한 후 비웁니다.
- authorities : 사용자에게 부여한 권한을 GrantedAuthority로 추상화하여 사용합니다.
Refresh Token 왜 나왔을까?
만약 JWT Token 에 있는 만료기간을 수정해서 보내게 된다면 서버에서 그 기간을 보고 결정하기 때문에 만료기간을
유저 마음대로 늘릴수 있다. 이러한 문제점 때문에 Refresh Token 이 나온것이다. 그러므로 JWT Token 을 사용한다면 Refresh Token 을 DB 에 저장하거나 Redis 에 저장을 하는것을 더 추천하지만 일단, 기한을 검증한다.
'Spring' 카테고리의 다른 글
QueryDSL (1) (2) | 2023.07.10 |
---|---|
Filter (0) | 2023.06.26 |
JWT (0) | 2023.06.26 |
@Configuration 쓰고 안쓰고의 차이점 (0) | 2023.06.24 |
Spring Retry (0) | 2023.06.19 |