跨域CORS

推荐阅读:

跨域访问是指请求一个与自身资源不同源(不同的域名、协议或端口)的资源。

CORS

浏览器出于安全考虑设置了同源策略,限制从脚本内发起跨域请求。但是实际应用中,往往常会发生跨域访问。因为,W3C提供了一个标准的跨域解决方案:跨域资源共享(Cross-Origin Resource Sharing),以支持安全的跨域请求和数据传输。
浏览器将CORS请求分为以下两类:

  • 简单请求
  • 预检请求:防止资源被本来没有权限的请求修改的保护机制。浏览器会在发送实际请求之前使用OPTIONS方法发送一个预检请求,从而获知服务器端是否允许该跨域请求。服务端确认允许后,才会发起实际的HTTP请求。
简单请求

满足以下条件的,属于简单请求:

  1. 请求方法是下面三种方法之一:
    • HEAD
    • GET
    • POST
  2. HTTP头信息不超过以下几种字段:
    • Cache-Control
    • Content-Language
    • Content-Type
      • 只限于三种:text/plain,multipart/form-data,application/x-www-form-urlencoded
    • Expires
    • Last-Modified
    • Pragma
    • DPR
    • Downlink
    • Save-Data
    • Viewport-Width
    • Width
预检请求

非简单请求为预检请求,会在正式通信之前触发一个OPTIONS请求进行预检。
image.png
预检请求会在请求头中附带一些正式请求的信息给服务端,主要有:

  • origin:请求源信息;
  • Access-Control-Request-Method:接下来的请求类型,如POST,GET等;
  • Access-Control-Request-Headers:接下来的请求中包含的用户显式设置的Header列表。

image.png
服务端接收请求后,会根据上述附带的信息判断是否允许跨域,通过响应头返回对应的信息:

  • Access-Control-Allow-Origin:允许跨域的 Origin 列表;
  • Access-Control-Allow-Methods:允许跨域的方法列表;
  • Access-Control-Allow-Headers:允许跨域的 Header 列表;
  • Access-Control-Expose-Headers:允许暴露的 Header 列表;
  • Access-Control-Max-Age:最大的浏览器缓存时间,单位:秒;
  • Access-Control-Allow-Credentials:是否允许发送 Cookie。

image.png
浏览器会根据返回的CORS信息判断是否发送真实的请求。以上行为都是浏览器自动完成的,服务端只需配置特定的CORS规则。

如何解决跨域访问问题?

最直接的方式:
设置为相同的域名、端口

添加跨域头

让服务器告诉浏览器:允许跨域(返回Access-Control-Allow-Origin响应头)

网关支持(nginx)
# 跨域配置
location ^~ /api/ {
    proxy_pass http://127.0.0.1:8080/api/;
    add_header 'Access-Control-Allow-Origin' $http_origin;
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
    add_header Access-Control-Allow-Headers '*';
    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Origin' $http_origin;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain; charset=utf-8';
        add_header 'Content-Length' 0;
        return 204;
    }
}

将之前的反向代理删掉:
image.png
将配置复制进去并保存:
image.png

修改后端项目
  1. 在控制器类上添加@CrossOrigin注解
@RestController
@RequestMapping("/user")
@CrossOrigin(origins = {"http://192.168.31.78:3000"}, allowCredentials = "true", maxAge = 3600)
public class UserController {
  1. 配置全局请求拦截器

@Configuration
public class WebMvcConfg implements WebMvcConfigurer {
 
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        //设置允许跨域的路径
        registry.addMapping("/**")
                //设置允许跨域请求的域名
                //当**Credentials为true时,**Origin不能为星号,需为具体的ip地址【如果接口不带cookie,ip无需设成具体ip】
                .allowedOrigins("http://localhost:9527", "http://127.0.0.1:9527", "http://127.0.0.1:8082", "http://127.0.0.1:8083")
                //是否允许证书 不再默认开启
                .allowCredentials(true)
                //设置允许的方法
                .allowedMethods("*")
                //跨域允许时间
                .maxAge(3600);
    }
}
  1. 定义新的CorsFilter
@Configuration
public class CorsConfig {
    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.setMaxAge(3600L);
        corsConfiguration.setAllowCredentials(true);
        return corsConfiguration;
    }
 
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig());
        return new CorsFilter(source);
    }
}

推荐阅读:SpringBoot设置Cors跨域的四种方式
配置好了后访问测试:
IE浏览器成功登录进入主页;
Chrome浏览器遇到问题了,跨站登录失效:





发现出问题了!登录成功后浏览器没有保存Cookie(IE可以正常访问)
黄色三角警告信息:

This Set-Cookie was blocked because it had the “Secure” attribute but was not received over a secure connection.

查阅相关资料,大概就是因为安全问题。浏览器迭代升级,secure表示Cookie的安全传输要求,当设置secure参数时,浏览器只会在使用HTTPS加密连接时将Cookie发送到服务器;samesite设置为none的意思是允许跨站点发送 Cookie,但是Chrome要求必须使用HTTPS传输Cookie,那就得考虑SSL证书了。简单了解了一下相关内容,网络安全还得多多学习!(不同浏览器、不同版本,相关默认参数有区别)

解决跨站Cookie SameSite限制(跨站登录失效)

跨站:eTLD+1(有效顶级域名+二级域名)不同
推荐阅读:

解决方式?

  1. 前后端地址不跨站
  2. HTTPS+SameSite=None

后端application.yml

server:
  servlet:
    session:
      cookie:
        same-site: none
        secure: true

这样配置后使用火狐可以访问,但是Chrome和IE不行,再加上SSL证书应该能实现所有用户访问。目前没有配置SSL证书
推荐阅读:

  • 23
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值