CORS跨域请求以及spring boot集成

同源策略 (same origin policy) 是浏览器安全的基石。在同源策略的限制下,非同源的网站之间不能发送 ajax 请求的。为了解决这个问题,W3C提出了CROS
CROS Cross-Origin Resource Sharing 跨域资源共享

简单请求

跨源时能够通过 script 或者 image 标签触发 GET 请求或通过表单发送一条 POST 请求,但这两种请求 HTTP 头信息中都不能包含任何自定义字段。
请求方法是 HEAD、GET 或 POST 且 HTTP 头信息不超过以下几个字段:Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type(只限于 application/x-www-form-urlencoded、multipart/form-data、text/plain)
ajax 进行跨域请求
如果需要ajax来请求的话,在头信息中添加一个 Origin 字段, 根据字段来判断是否需要在http响应头上添加Access-Control-Allow-Origin 字段,是否返回正确的结果。
因为浏览器先于用户得到返回结果,根据有无 Access-Control-Allow-Origin 字段来决定是否拦截该返回结果。

其他的参数
Access-Control-Allow-Credentials:可选,用户是否可以发送、处理 cookie。
Access-Control-Expose-Headers:可选,可以让用户拿到的字段。有几个字段无论设置与否都可以拿到的,包括:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。

非简单请求(除简单请求之外的)

需要增加一次OPTIONS请求,称为预检请求,预检请求将真实请求的信息,包括请求方法、自定义头字段、源信息添加到 HTTP 头信息字段中,询问服务器是否允许这样的操作。
比如 delete 请求

OPTIONS /test HTTP/1.1
Origin: http://www.examples.com
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: X-Custom-Header
Host: www.examples.com

与 CORS 相关的字段有:

Access-Control-Request-Method: 真实请求使用的 HTTP 方法。
Access-Control-Request-Headers: 真实请求中包含的自定义头字段。
服务器收到请求时,需要分别对 Origin、Access-Control-Request-Method、Access-Control-Request-Headers 进行验证,验证通过后,会在返回 Http 头信息中添加

Access-Control-Allow-Origin: http://www.examples.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000

他们的含义分别是:

Access-Control-Allow-Methods: 真实请求允许的方法
Access-Control-Allow-Headers: 服务器允许使用的字段
Access-Control-Allow-Credentials: 是否允许用户发送、处理 cookie
Access-Control-Max-Age: 预检请求的有效期,单位为秒。有效期内,不会重复发送预检请求
当预检请求通过后,浏览器会发送真实请求到服务器。这就实现了跨源请求。

spring boot集成CORS

单个类或者url配置

CrossOrigin(origins = {"http://localhost:9000", "null"})

全局配置

方式一 使用CorsConfiguration

@Bean
public FilterRegistrationBean corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);   config.addAllowedOrigin("http://localhost:9000");
    config.addAllowedOrigin("null");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/**", config); // CORS 配置对所有接口都有效
    FilterRegistrationBean bean = newFilterRegistrationBean(new CorsFilter(source));
    bean.setOrder(0);
    return bean;
}

ps 这里的CorsFilter 是org.springframework.web.filter, 他最终实现的是javax.servlet.Filter
方式二 自定义Filter, 这种方式更加灵活
新增一个类corsFilter,实现Filter接口,在doFilter方法里面,对response添加header,加origin.

@Component("corsFilter") 
public class CorsFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if (response instanceof HttpServletResponse) {
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.addHeader("Access-Control-Allow-Origin", "*");
            httpResponse.addHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
            httpResponse.addHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With");
        }
        chain.doFilter(request, response);
    }
    @Override
    public void destroy() {
    }
}
@Bean
    public FilterRegistrationBean additionalFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(corsFilter);
        registration.setEnabled(true);
        registration.addUrlPatterns("/*");
        registration.setName("corsFilter");
        return registration;
    }

参考博文:

https://blog.coding.net/blog/spring-mvc-cors

你可能感兴趣的:(spring,spring,ajax)