일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- queryDSL
- Q 클래스
- Filter
- 1차캐시
- 스프링부트오류
- 스프링 부트 기능
- ERD 작성
- jpa에러
- JPA
- uncheck Exception
- 최종 프로젝트
- Unsatisfied dependency
- Spring Spring boot 차이
- 스프링 부트 공식 문서
- JoinColumn
- JPA주의사항
- spring서버
- 복합키
- github
- jpa회원가입
- jwt메서드
- 빈생성안됨
- git
- REST API 규칙
- json
- json gson 차이
- 인텔리제이
- @IdClass
- Error creating bean with name
- REST란
- Today
- Total
Everyday Dev System
Spring 에서 Filter란? 본문
Spring Boot에서 Server는 Client로 부터 요청이 들어오면 Filter를 거치게 되어 있다.
요청이 들어오고 FIlter를 통해 인증을 한 후
인증이 완료된 경우 Securitycontext에 authority를 넣어준다.
그리고 권한 확인을 하고 , Controller로 이동한다.
아래와 같이 Filter interface를 상속받아 doFilter()를 재정의하여 커스튬한 Filter를
SpringBoot의 기본적으로 구현되어 있는 필터의 순서에 끼워 넣어서 Filter로서 기능을 수행시킬 수 있다.
.addFilterBefore(A,B) -> B Filter 이전에 A Filter를 먼저 거친다.
Filter를 커스튬하기 위해 상속받을 수 있는 Filter의 종류는 많은데 그 중 현업에서 주로 활용하는 것이
한 요청마다 거치는 FIlter -> OncePerRequestFilter 이다.
Filter를 거쳐서 권한을 부여받고 그 권한을 Http.authorizeRequest() 코드에서
해당 url에 따른 권한을 매칭시켜 확인 하는 것이다.
예를 들어,
public class LshFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
SecurityContextHolder.setContext(new SecurityContextImpl(new UsernamePasswordAuthenticationToken("lsh", "lsh")));
}
}
OncePerRequestFilter extend한 Filter Class를 생성한 후 , doFiltertInternal를 재구현한다.
SecutiryContextHolder.setContext(new SecurityContext( new UsernamePasswordAuthenticationToken("dslkj","sd"));
해당 필터에서는 아무것도 안하고 권한 부여하는 코드로 작성되어 있다.
권한 부여는 SecurityContextHolder를 통해 SecurityContext에 UsernamePasswordAuthenticationToken을 저장한다. 인증처리가 완료가 됨을 뜻함.
그 후, Config 클래스에서
http.addFilterBefore(new LshFilter() , UsernamePasswordAuthenticationFilter.class);
.addFilterBefore(A,B) -> B Filter 이전에 A Filter를 먼저 거친다.
httip.authorizeRequest
.antMatchers("/lsh").hasRole("lsh");
위 코드를 통해 해당 url에 따른 권한을 매칭시켜 확인 하고 인가하는 것이다.
인가가 허락되지 않으면 예외처리를 작성하여 처리할 수 있다.
위와 같은 순서로 필터를 통해 인증 절차 -> 권한 부여 -> url에 따른 권한 확인 -> 인가 절차
references :
Spring Security의 권한 부여 처리 흐름 (velog.io)
예제 코드:
1. 요청했을 때 들어오는 URL을 Logging 처리 하는 Filter
package com.sparta.springauth.filter;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Slf4j(topic = "LoggingFilter")
@Component
@Order(1) // filter 순서 지정
public class LoggingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 전처리
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String url = httpServletRequest.getRequestURI();
log.info(url);
chain.doFilter(request, response); // 다음 Filter 로 이동
// 후처리
log.info("비즈니스 로직 완료");
}
}
@Order(1)
filter 순서 지정
url을 가져오기 위해 HttpServletRequest 타입으로 캐스팅하고 가져옴.
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String url = httpServletRequest.getRequestURI();
2. 인증 및 인가를 처리하는 Filter
package com.sparta.springauth.filter;
import com.sparta.springauth.entity.User;
import com.sparta.springauth.jwt.JwtUtil;
import com.sparta.springauth.repository.UserRepository;
import io.jsonwebtoken.Claims;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.IOException;
@Slf4j(topic = "AuthFilter")
@Component
@Order(2)
public class AuthFilter implements Filter {
private final UserRepository userRepository;
private final JwtUtil jwtUtil;
public AuthFilter(UserRepository userRepository, JwtUtil jwtUtil) {
this.userRepository = userRepository;
this.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");
}
}
}
}
'내배캠 주요 학습 > Spring 숙련' 카테고리의 다른 글
중요한 Validation, 예외처리 (0) | 2023.06.20 |
---|---|
Spring Secutiry (0) | 2023.06.20 |
로그인 구현하기 (0) | 2023.06.19 |
회원가입 구현하기 (0) | 2023.06.19 |
JWT version 0.11.5 (0) | 2023.06.19 |