Http跨域解决方案

简单请求

满足发下条件会被视为简单请求:
1、使用下列请求方法之一:

  • GET
  • HEAD
  • POST

2、请求头信息不超出以下几种:

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type 仅限于以下三者
    text/plain
    multipart/form-data
    application/x-www-form-urlencoded

简单请求会在请求头添加 Origin 字段,服务器根据这个值来决定是否同意这次请求。如果同请求,服务器响应会额外添加几个字段:

  • Access-Control-Allow-Origin(必须)
    指定了允许访问该资源的域,其值要么是请求时 Origin 的值,要么是 * 表示接受任意域名的请求;
    当指定的值不是 * 时,响应首部中的 Vary 字段的值必须包含 Origin;
  • Access-Control-Allow-Credentials(可选)
    当浏览器的credentials设置为true时,是否允许浏览器读取response的内容;
    返回true(唯一有效值,区分大小写)则可以,其他值均不可以。
    此字段返回true时,Access-Control-Allow-Origin 必须为请求 Origin 的值,不能是 *;
    此字段在预检请求的响应中时,它指定了实际的请求是否可以使用credentials;
    简单请求不会被预检,当浏览器的credentials设置为true时,其响应中如果不包含该字段,浏览器将无法读取response的内容。
  • Access-Control-Expose-Headers(可选):
    白名单,列出了服务器允许浏览器访问的头;
    默认情况下,XMLHttpRequest.getResponseHeader() 方法只能拿到六种简单响应首部,如果想要能拿到其它字段,就需要在Access-Control-Expose-Headers指定。

    六种简单响应首部是:
    Cache-Control
    Content-Language
    Content-Type
    Expires
    Last-Modified
    Pragma

非简单请求

非简单请求是那种对服务器有特殊要求的请求
比如请求方法是 PUT 或 DELETE;
比如包含了限定以外的请求头,如 Authorization 或 X-Custom-Header;
比如 Content-Type 字段值是 application/json;
对于非简单请求,浏览器会先发起一个预检请求,得到肯定答复后,才会发起正式请求。

预检请求

预检请求使用 OPTIONS 方法,包括以下字段:

  • Origin: 表明实际请求的源站;
  • Access-Control-Request-Method: 表明实际请求所使用的 HTTP 方法;
  • Access-Control-Request-Headers: 表明实际请求所额外携带的头部字段;

注:预检请求由浏览器自动发出,无须手动设置这些字段。

预检请求的响应

服务器收到预检请求后,检查了 Origin, Access-Control-Request-Method, Access-Control-Request-Headers 后,可以确认是否允许跨源请求,然后做出回应。

响应包括以下字段:

  • Access-Control-Allow-Origin 指定了允许访问该资源的域,含义同简单请求
  • Access-Control-Allow-Methods 指定了实际请求中允许使用的所有HTTP方法
  • Access-Control-Allow-Headers 指定了实际请求中允许携带的所有首部字段
  • Access-Control-Allow-Credentials 指定了实际的请求是否可以使用credentials,含义同简单请求
  • Access-Control-Max-Age 指定了预检请求的结果能够被缓存多久,单位秒

正常跨域请求

通过预检后,正常跨域请求跟简单请求一样,浏览器会在请求头添加 Origin 字段;
服务器的回应也跟简单请求一样,必须包含 Access-Control-Allow-Origin 字段。

SprinBoot中跨域的三种解决方法

CrossOrigin注解

//@CrossOrigin  表示所有的URL均可访问此资源
@CrossOrigin(origins = "http://127.0.0.1:8093")//表示只允许这一个url可以跨域访问这个controller
@RestController
@RequestMapping("/testCorss")
public class CorssOriginController {
    //可以对方法运用该注解
    //@CrossOrigin(origins = "http://127.0.0.1:8093")
    @GetMapping("/getString")
    public String getString(){
        return "跨域成功!";
    }
}

@CrossOrigin这个注解用起来很方便,这个可以用在方法上,也可以用在类上。如果你不设置他的value属性,或者是origins属性,就默认是可以允许所有的URL/域访问。

  • value属性可以设置多个URL。
  • origins属性也可以设置多个URL。
  • maxAge属性指定了准备响应前的缓存持续的最大时间。就是探测请求的有效期。
  • allowCredentials属性表示用户是否可以发送、处理 cookie。默认为false
  • allowedHeaders 属性表示允许的请求头部有哪些。
  • methods 属性表示允许请求的方法,默认get,post,head。

实现WebMvcConfigurer

public class MyWebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/testCross/**")
                .allowedHeaders("*")
                .allowedMethods("*")
                .allowCredentials(true)
                .allowedOrigins("http://localhost:8093")
                .maxAge(2000);
    }
}

重写addCorsMappings方法就行,配置好参数,参数和上面的注解的参数类似。这个配置属于全局配置,配置好了全部的接口都遵循此规则。上面的注解方式只对类或者方法生效。addMaping是设置对那种格式的URL生效,也就是跟在URL后面的路径。

过滤器配置

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

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

利用过滤器配置实现跨域,还有另外一种方法

import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.FilterConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Configuration
public class CorssFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse) response;
        res.addHeader("Access-Control-Allow-Credentials", "true");
        res.addHeader("Access-Control-Allow-Origin", "http://localhost:8093");
        res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
        res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN");
        chain.doFilter(request, response);
    }
    @Override
    public void destroy() {
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值