001/* 002 * Copyright 2002-2019 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.filter; 018 019import java.io.IOException; 020 021import javax.servlet.FilterChain; 022import javax.servlet.ServletException; 023import javax.servlet.http.HttpServletRequest; 024import javax.servlet.http.HttpServletResponse; 025 026import org.springframework.util.Assert; 027import org.springframework.web.cors.CorsConfiguration; 028import org.springframework.web.cors.CorsConfigurationSource; 029import org.springframework.web.cors.CorsProcessor; 030import org.springframework.web.cors.CorsUtils; 031import org.springframework.web.cors.DefaultCorsProcessor; 032import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 033 034/** 035 * {@link javax.servlet.Filter} that handles CORS preflight requests and intercepts 036 * CORS simple and actual requests thanks to a {@link CorsProcessor} implementation 037 * ({@link DefaultCorsProcessor} by default) in order to add the relevant CORS 038 * response headers (like {@code Access-Control-Allow-Origin}) using the provided 039 * {@link CorsConfigurationSource} (for example an {@link UrlBasedCorsConfigurationSource} 040 * instance. 041 * 042 * <p>This is an alternative to Spring MVC Java config and XML namespace CORS configuration, 043 * useful for applications depending only on spring-web (not on spring-webmvc) or for 044 * security constraints requiring CORS checks to be performed at {@link javax.servlet.Filter} 045 * level. 046 * 047 * <p>This filter could be used in conjunction with {@link DelegatingFilterProxy} in order 048 * to help with its initialization. 049 * 050 * @author Sebastien Deleuze 051 * @since 4.2 052 * @see <a href="https://www.w3.org/TR/cors/">CORS W3C recommendation</a> 053 */ 054public class CorsFilter extends OncePerRequestFilter { 055 056 private final CorsConfigurationSource configSource; 057 058 private CorsProcessor processor = new DefaultCorsProcessor(); 059 060 061 /** 062 * Constructor accepting a {@link CorsConfigurationSource} used by the filter 063 * to find the {@link CorsConfiguration} to use for each incoming request. 064 * @see UrlBasedCorsConfigurationSource 065 */ 066 public CorsFilter(CorsConfigurationSource configSource) { 067 Assert.notNull(configSource, "CorsConfigurationSource must not be null"); 068 this.configSource = configSource; 069 } 070 071 072 /** 073 * Configure a custom {@link CorsProcessor} to use to apply the matched 074 * {@link CorsConfiguration} for a request. 075 * <p>By default {@link DefaultCorsProcessor} is used. 076 */ 077 public void setCorsProcessor(CorsProcessor processor) { 078 Assert.notNull(processor, "CorsProcessor must not be null"); 079 this.processor = processor; 080 } 081 082 083 @Override 084 protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, 085 FilterChain filterChain) throws ServletException, IOException { 086 087 CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(request); 088 boolean isValid = this.processor.processRequest(corsConfiguration, request, response); 089 if (!isValid || CorsUtils.isPreFlightRequest(request)) { 090 return; 091 } 092 filterChain.doFilter(request, response); 093 } 094 095}