Spring Security 상용 필터 인 스 턴 스 분석

10461 단어 SpringSecurity필터
Spring Security 에서 흔히 볼 수 있 는 15 개의 차단기
1 . org.springframework.security.web.context.SecurityContextPersistenceFilter
가장 중요 한 필 터 는 역할 이 중요 하 므 로 더 이상 말 할 필요 가 없다.
  • Security ContextPersistence Filter 는 주로 Security ContextRepository 를 사용 하여 session 에서 하 나 를 저장 하거나 업데이트 합 니 다
  • Security Context,그리고 Security Context 를 다음 필터 에 사용 하여 후속 filter 에 필요 한 컨 텍스트 를 만 듭 니 다
  • 4.567917.Security Context 에 현재 사용자 의 인증 과 권한 정 보 를 저장 합 니 다2 . org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter
    이 필 터 는 Security Context 를 Spring 비동기 실행 체제 의 WebAsyncManager 로 통합 하 는 데 사 용 됩 니 다.
    3 . org.springframework.security.web.header.HeaderWriterFilter
    요청 한 Header 에 해당 하 는 정 보 를 추가 하면 http 탭 내부 에서 security:headers 를 사용 하여 제어 할 수 있 습 니 다.
    4 . org.springframework.security.web.csrf.CsrfFilter
    csrf 는 크로스 도 메 인 위조 요청 이 라 고도 부 릅 니 다.SpringSecurity 는 모든 post 에 시스템 생 성 csrf 의 token 정 보 를 포함 하 는 지 검증 을 요청 합 니 다.
    포함 되 지 않 으 면 잘못 을 보고 합 니 다.csrf 공격 을 방지 하 는 효과 가 있 습 니 다.
    5. org.springframework.security.web.authentication.logout.LogoutFilter
    URL 이/logout 인 요청 과 일치 하여 사용자 가 종료 하고 인증 정 보 를 삭제 합 니 다.
    6 . org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
    인증 작업 은 모두 이 필터 에 의 해 이 루어 집 니 다.기본 URL 은/login 이 고 POST 요청 이 어야 합 니 다.
    7 . org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter
    설정 파일 에 인증 페이지 를 지정 하지 않 으 면 이 필터 로 기본 인증 페이지 를 만 듭 니 다.
    8 . org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter
    이 필 터 는 로그 인 페이지 에서 기본 종료 페이지 를 만 들 수 있 습 니 다.
    9 . org.springframework.security.web.authentication.www.BasicAuthenticationFilter
    이 필 터 는 HTTP 요청 의 머리 이름 이 Authentication 이 고 Basic 으로 시작 하 는 머리 정 보 를 자동 으로 해석 합 니 다.
    10 . org.springframework.security.web.savedrequest.RequestCacheAwareFilter
    HttpSession RequestCache 내 부 를 통 해 HttpServletRequest 캐 시 에 사용 할 RequestCache 를 유 지 했 습 니 다.
    11 . org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter
    ServletRequest 에 대한 포장 을 진행 하여 request 가 더욱 풍부 한 API 를 가지 도록 합 니 다.
    12 . org.springframework.security.web.authentication.AnonymousAuthenticationFilter
    Security ContextHolder 에서 인증 정보 가 비어 있 으 면 익명 의 사용 자 를 만들어 Security ContextHolder 에 저장 합 니 다.
    spring security 는 로그 인 되 지 않 은 방문 을 호 환 하기 위해 인증 절 차 를 밟 았 습 니 다.익명 의 신분 에 불과 합 니 다.
    13 . org.springframework.security.web.session.SessionManagementFilter
    Security ContextRepository 는 같은 사용자 가 여러 세 션 을 여 는 수량 을 제한 합 니 다.
    14 . org.springframework.security.web.access.ExceptionTranslationFilter
    이상 변환 필 터 는 전체 spring Security FilterChain 의 후방 에 위치 하여 전체 링크 에 나타 난 이상 을 변환 합 니 다.
    15 . org.springframework.security.web.access.intercept.FilterSecurityInterceptor
    설정 한 자원 접근 권한 수여 정 보 를 가 져 오고 Security ContextHolder 에 저 장 된 사용자 정보 에 따라 권한 이 있 는 지 여 부 를 결정 합 니 다.
    그렇다면 spring security 에 모두 이렇게 많은 필터 가 있 는 것 일 까?정 답 은 부정!spring-security.xml 설정 이 추가 되면 서
    새로운 필터 가 나타 납 니 다.
    그렇다면 spring security 는 매번 이 필 터 를 불 러 오지 않 습 니까?답 도 부정 적!spring-security.xml 설정 에 따라 수정 되 었 습 니 다.
    일부 필 터 는 지 워 질 수 있 습 니 다.
    spring security 필터 체인 로드 원리
    
    public class DelegatingFilterProxy extends GenericFilterBean {
    @Nullable
    private String contextAttribute;
    @Nullable
    private WebApplicationContext webApplicationContext;
    @Nullable
    private String targetBeanName;
    private boolean targetFilterLifecycle;
    @Nullable
    private volatile Filter delegate;// :               
    private final Object delegateMonitor;
    // :doFilter        ,     !
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain
    filterChain) throws ServletException, IOException {
    Filter delegateToUse = this.delegate;
    if (delegateToUse == null) {
    synchronized(this.delegateMonitor) {
    delegateToUse = this.delegate;
    if (delegateToUse == null) {
    WebApplicationContext wac = this.findWebApplicationContext();
    if (wac == null) {
    throw new IllegalStateException("No WebApplicationContext found: no
    ContextLoaderListener or DispatcherServlet registered?");
    }
    //   :doFilter       ,            delegate
    delegateToUse = this.initDelegate(wac);
    }
    this.delegate = delegateToUse;
    }
    }
    //   :  FilterChainProxy   
    this.invokeDelegate(delegateToUse, request, response, filterChain);
    }
    //   :               
    protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
    //debug  targetBeanName :springSecurityFilterChain
    String targetBeanName = this.getTargetBeanName();
    Assert.state(targetBeanName != null, "No target bean name set");
    //debug  delegate   :FilterChainProxy
    Filter delegate = (Filter)wac.getBean(targetBeanName, Filter.class);
    if (this.isTargetFilterLifecycle()) {
    delegate.init(this.getFilterConfig());
    }
    return delegate;
    }
    protected void invokeDelegate(Filter delegate, ServletRequest request, ServletResponse
    response, FilterChain filterChain) throws ServletException, IOException {
    delegate.doFilter(request, response, filterChain);
    }
    }
    두 번 째 debug 결 과 는 다음 과 같 습 니 다.


    이 를 통 해 알 수 있 듯 이 Delegating FilterProxy 는 spring Security FilterChain 이라는 이름 을 통 해 FilterChain Proxy 필 터 를 얻 었 습 니 다.
    결국 세 번 째 단계 에서 이 필 터 를 실행 했다.
    FilterChainProxy
    
    public class FilterChainProxy extends GenericFilterBean {
    private static final Log logger = LogFactory.getLog(FilterChainProxy.class);
    private static final String FILTER_APPLIED =
    FilterChainProxy.class.getName().concat(".APPLIED");
    private List<SecurityFilterChain> filterChains;
    private FilterChainProxy.FilterChainValidator filterChainValidator;
    private HttpFirewall firewall;
    // !?       SecurityFilterChain         FilterChainProxy  
    // FilterChainProxy      ?              ?       !
    public FilterChainProxy(SecurityFilterChain chain) {
    this(Arrays.asList(chain));
    }
    //  SecurityFilterChain   !     !
    public FilterChainProxy(List<SecurityFilterChain> filterChains) {
    this.filterChainValidator = new FilterChainProxy.NullFilterChainValidator();
    this.firewall = new StrictHttpFirewall();
    this.filterChains = filterChains;
    }
    // :   doFilter 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    throws IOException, ServletException {
    boolean clearContext = request.getAttribute(FILTER_APPLIED) == null;
    if (clearContext) {
    try {
    request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
    this.doFilterInternal(request, response, chain);
    } finally {
    SecurityContextHolder.clearContext();
    request.removeAttribute(FILTER_APPLIED);
    }
    } else {
    //   :         doFilterInternal   
    this.doFilterInternal(request, response, chain);
    }
    }
    private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain
    chain) throws IOException, ServletException {
    FirewalledRequest fwRequest =
    this.firewall.getFirewalledRequest((HttpServletRequest)request);
    HttpServletResponse fwResponse =
    this.firewall.getFirewalledResponse((HttpServletResponse)response);
    //   :          ,                !
    List<Filter> filters = this.getFilters((HttpServletRequest)fwRequest);
    if (filters != null && filters.size() != 0) {
    FilterChainProxy.VirtualFilterChain vfc = new
    FilterChainProxy.VirtualFilterChain(fwRequest, chain, filters);
    //   :      
    vfc.doFilter(fwRequest, fwResponse);
    } else {
    if (logger.isDebugEnabled()) {
    logger.debug(UrlUtils.buildRequestUrl(fwRequest) + (filters == null ? " has no
    matching filters" : " has an empty filter list"));
    }
    fwRequest.reset();
    chain.doFilter(fwRequest, fwResponse);
    }
    }
    private List<Filter> getFilters(HttpServletRequest request) {
    Iterator var2 = this.filterChains.iterator();
    //   :       SecurityFilterChain !
    SecurityFilterChain chain;
    do {
    if (!var2.hasNext()) {
    return null;
    }
    chain = (SecurityFilterChain)var2.next();
    } while(!chain.matches(request));
    return chain.getFilters();
    }
    }

    SecurityFilterChain
    마지막 으로 Security FilterChain 을 보십시오.이것 은 인터페이스 입 니 다.실현 클래스 도 하나 입 니 다.이것 이 야 말로 웹.xml 에 설 치 된 필터 체인 대상 입 니 다!
    
    public interface SecurityFilterChain {
      boolean matches(HttpServletRequest request);
      List<Filter> getFilters();
    }
    
    
    public final class DefaultSecurityFilterChain implements SecurityFilterChain {
      private static final Log logger = LogFactory.getLog(DefaultSecurityFilterChain.class);
      private final RequestMatcher requestMatcher;
      private final List<Filter> filters;
    
      public DefaultSecurityFilterChain(RequestMatcher requestMatcher, Filter... filters) {
        this(requestMatcher, Arrays.asList(filters));
      }
    
      public DefaultSecurityFilterChain(RequestMatcher requestMatcher, List<Filter> filters) {
        logger.info("Creating filter chain: " + requestMatcher + ", " + filters);
        this.requestMatcher = requestMatcher;
        this.filters = new ArrayList<>(filters);
      }
    
      public RequestMatcher getRequestMatcher() {
        return requestMatcher;
      }
    
      public List<Filter> getFilters() {
        return filters;
      }
    
      public boolean matches(HttpServletRequest request) {
        return requestMatcher.matches(request);
      }
    
      @Override
      public String toString() {
        return "[ " + requestMatcher + ", " + filters + "]";
      }
    }

    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기