当前位置: 首页 > wzjs >正文

微网站 微信网站开发图片框

微网站 微信,网站开发图片框,vue 做双语版网站,2021年十大热点事件跨域访问CORS 原理基本概念简单请求非简单请求(预检请求) 代码实现服务器端Cors的关键配置服务端解析预检请求服务端填充响应 抓包分析 原理 基本概念 在浏览器安全模型中,同源策略是最重要的安全基石。 一个“域”是由3个要素组成的&#…

跨域访问CORS

    • 原理
      • 基本概念
      • 简单请求
      • 非简单请求(预检请求)
    • 代码实现
      • 服务器端Cors的关键配置
      • 服务端解析预检请求
      • 服务端填充响应
    • 抓包分析

原理

基本概念

在浏览器安全模型中,同源策略是最重要的安全基石。
一个“域”是由3个要素组成的:

  • 协议(如:http 或 https)
  • 主机(Host,如 www.example.com 或 127.0.0.1)
  • 端口(Port,如 80 或 8080)

只要这三个完全一致,就是同源的。
例如

  • http://example.com:80 和 http://example.com:8080 是不同源
  • http://example.com 和 https://example.com 是不同源

下面是官网解释跨域的图解:
在这里插入图片描述

两种请求:浏览器将 CORS 请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。

简单请求

按照 W3C 的 CORS 规范,只有完全满足「安全要求」的跨域请求,浏览器才会把它直接当成简单请求,直接发送给服务端,不需要先发 OPTIONS。
必须同时满足以下条件

  1. 请求方法必须是(GET/HEAD/POST)三者之一
  2. 请求头不能超出以下几个字段(Accept、Accept-Language、Content-Language、Content-Type)等
  3. Content-Type(如果存在的话),其值只能是application/x-www-form-urlencoded、multipart/form-data、text/plain

非简单请求(预检请求)

非简单请求是指那些对服务器有特殊要求的请求,例如:

  • 使用PUT或DELETE方法
  • 设置Content-Type为application/json
    即不满足简单请求的条件的都是预检请求(非简单请求)。

对于这类请求,浏览器会在正式通信前额外发送一次HTTP查询请求(即预检请求),这个过程叫做预检(Preflight)。该请求会确认:

  1. 当前网页域名是否在服务器的许可名单中
  2. 允许使用的HTTP方法和头信息字段
    只有在获得服务器肯定答复后,浏览器才会发出正式的XMLHttpRequest请求,否则将报错。

“预检请求”用的请求方法是 OPTIONS,表示这个请求是用来询问的。头信息里面,关键字是 Origin,表示请求来自哪个源。
除了 Origin 字段,“预检请求”的头信息包括两个特殊字段。
Access-Control-Request-Method:必须字段,列出浏览器的 CORS 请求会用到哪些 HTTP 方法;
Access-Control-Request-Headers:这个字段是一个逗号 , 分隔的字符串,指定浏览器 CORS 请求会额外发送的头信息字段,上面示例是 X-Custom-Header。

代码实现

CORS(Cross-Origin Resource Sharing,跨域资源共享)通过在响应头里加上一组特殊字段来告诉浏览器,这个资源允许被某些源访问。

服务器端Cors的关键配置

struct CorsConfig 
{std::vector<std::string> allowedOrigins;//允许哪些域名可以访问std::vector<std::string> allowedMethods; //允许哪些方法可以跨域调用std::vector<std::string> allowedHeaders; //允许前端请求里带哪些请求头bool allowCredentials = false; //不允许携带Cookie/Authorization header/TLS client cert 这类凭证信息int maxAge = 3600;             //浏览器缓存预检请求的最大时长, 1 小时内同样的跨域请求只会发送一次 OPTIONS,之后直接用缓存的结果static CorsConfig defaultConfig() {CorsConfig config;config.allowedOrigins = {"*"}; //这里允许的是所有域名config.allowedMethods = {"GET", "POST", "PUT", "DELETE", "OPTIONS"}; //在预检请求(OPTIONS)的响应里告诉浏览器:后端接受哪些方法config.allowedHeaders = {"Content-Type", "Authorization"}; //允许前端带Content-Type(比如 application/json)和Authorization(携带JWT Token等)return config;}
};

服务端解析预检请求

处理客户端发来的请求的流程如下:

  1. 判断是否是预检请求,如果是,进入下一步;否则不做处理(正常的请求,继续后续的处理流程,响应)
  2. 检查当前请求的源是否被允许,如果允许当前请求源则在响应头中添加该源字段,状态码为204 No content,响应体为空,进入下一步
  3. 直接抛出特殊的响应对象(中断后续的处理流程)

总结:如果是预检请求,设置Cors的相关字段,直接返回;否则就进入正常的处理流程。

/***  @brief 请求前钩子,所有请求进来时都会先执行* 如果是跨域的 OPTIONS 预检请求,直接构造响应并抛出,跳过后续中间件/路由逻辑。*/
void CorsMiddleware::before(HttpRequest& request) 
{LOG_DEBUG << "CorsMiddleware::before - Processing request";// 如果是浏览器发起的预检请求(CORS Preflight)if (request.method() == HttpRequest::Method::kOptions) {LOG_INFO << "Processing CORS preflight request";HttpResponse response;  // 创建预检响应handlePreflightRequest(request, response);// 直接中断后续处理流程,抛出特殊的响应对象throw response;}
}/*** @brief 处理 CORS 预检请求(OPTIONS)* 会校验 Origin,并返回允许的跨域头*/
void CorsMiddleware::handlePreflightRequest(const HttpRequest& request, HttpResponse& response) 
{   // 从请求头获取 Originconst std::string& origin = request.getHeader("Origin");// 校验是否允许跨域if (!isOriginAllowed(origin)) {LOG_WARN << "Origin not allowed: " << origin;response.setStatusCode(HttpResponse::k403Forbidden);return;}// 添加允许的跨域头,对预检请求返回 204 No Content;//即响应体为空,对应返回的是options字段的预检请求的响应addCorsHeaders(response, origin);response.setStatusCode(HttpResponse::k204NoContent);LOG_INFO << "Preflight request processed successfully";
}/*** @brief 检查给定 Origin 是否在允许列表里* @param origin 来自浏览器请求头的 Origin* @return true 如果允许跨域,否则 false*/
bool CorsMiddleware::isOriginAllowed(const std::string& origin) const 
{return config_.allowedOrigins.empty() || std::find(config_.allowedOrigins.begin(), config_.allowedOrigins.end(), "*") != config_.allowedOrigins.end() ||std::find(config_.allowedOrigins.begin(), config_.allowedOrigins.end(), origin) != config_.allowedOrigins.end();}/*** @brief 给响应添加标准的 CORS 头信息* @param response 当前响应对象* @param origin 本次请求允许的 Origin*/
void CorsMiddleware::addCorsHeaders(HttpResponse& response, const std::string& origin) 
{try {   // 设置允许的 Originresponse.addHeader("Access-Control-Allow-Origin", origin);// 是否允许携带 cookieif (config_.allowCredentials) {response.addHeader("Access-Control-Allow-Credentials", "true");}// 设置允许的方法列表,以,分割if (!config_.allowedMethods.empty()) {response.addHeader("Access-Control-Allow-Methods", join(config_.allowedMethods, ", "));}// 设置允许的自定义请求头列表if (!config_.allowedHeaders.empty()) {response.addHeader("Access-Control-Allow-Headers", join(config_.allowedHeaders, ", "));}// 设置预检结果的缓存时间(单位:秒)response.addHeader("Access-Control-Max-Age", std::to_string(config_.maxAge));LOG_DEBUG << "CORS headers added successfully";} catch (const std::exception& e) {LOG_ERROR << "Error adding CORS headers: " << e.what();}
}
/*** @brief 工具函数:把字符串数组用指定分隔符拼接起来* @param strings 字符串列表* @param delimiter 分隔符,如 ", "* @return 拼接后的字符串*/
std::string CorsMiddleware::join(const std::vector<std::string>& strings, const std::string& delimiter) 
{std::ostringstream result;for (size_t i = 0; i < strings.size(); ++i) {if (i > 0) result << delimiter;result << strings[i];}return result.str();
}

服务端填充响应

这里的响应指的是正常处理客户端发来的请求后,在最终的响应头中添加CORS的相关信息

/*** @brief 请求后钩子,正常请求处理完毕后执行。* 不管是否跨域,都会在最终响应头里加上 CORS 相关头信息。*/
void CorsMiddleware::after(HttpResponse& response) 
{LOG_DEBUG << "CorsMiddleware::after - Processing response";// 直接添加CORS头,简化处理逻辑if (!config_.allowedOrigins.empty()) {// 如果允许所有源if (std::find(config_.allowedOrigins.begin(), config_.allowedOrigins.end(), "*") != config_.allowedOrigins.end()) {addCorsHeaders(response, "*");} else {// 简单处理:只取第一个允许的来源(可以按需改成匹配实际请求来源)addCorsHeaders(response, config_.allowedOrigins[0]);}}
}

抓包分析

在这里插入图片描述
在这里插入图片描述
上图展示了请求与响应的抓包分析数据:当客户端向服务器请求加载登录页面时,服务器不仅会在响应体中返回HTML文件,还会在响应头中附带CORS配置信息供浏览器解析。
CORS 详解,终于不用担心跨域问题了


文章转载自:

http://dl2KLkFn.qqzdr.cn
http://90CHZWbL.qqzdr.cn
http://uHEXQZmv.qqzdr.cn
http://2L4dWRLf.qqzdr.cn
http://aC5Ae8eI.qqzdr.cn
http://rgpRn2hD.qqzdr.cn
http://ooBI2GaW.qqzdr.cn
http://imf1Zkw8.qqzdr.cn
http://VxA8lqz9.qqzdr.cn
http://ls8yMDgG.qqzdr.cn
http://5g6tSwvG.qqzdr.cn
http://1Oenl6Vq.qqzdr.cn
http://HKYwuybH.qqzdr.cn
http://IZ4UvzM6.qqzdr.cn
http://USE2nWPL.qqzdr.cn
http://SewNyiQ3.qqzdr.cn
http://WnoBTOwv.qqzdr.cn
http://iWDZtRav.qqzdr.cn
http://YgtnctLE.qqzdr.cn
http://qlkM3M1E.qqzdr.cn
http://FyVMXBcz.qqzdr.cn
http://AckPga2M.qqzdr.cn
http://FA9JK9vp.qqzdr.cn
http://EcIJ4qgp.qqzdr.cn
http://heoNUoVB.qqzdr.cn
http://xhfR5SSY.qqzdr.cn
http://p5WAdnha.qqzdr.cn
http://bA5CXxLP.qqzdr.cn
http://z0GclqCK.qqzdr.cn
http://DOjaGC22.qqzdr.cn
http://www.dtcms.com/wzjs/769383.html

相关文章:

  • 能做网站的网站陕西做网站公司
  • 个人作品集网站模板免费下载网站网络投票建设步骤
  • 怎么制作网站详细教程视频网页设计与制作实用教程(第3版)
  • 网站开发工程师要求网站建设推广选stso88效果好
  • 如何网站建设 需要详细的步骤wordpress页面大小调节
  • 做网站用图片算侵犯著作权吗做网站需要相机吗
  • 雅客网站建设网站建设需要哪些证件
  • 美发网站模板带手机版企业网站建设的要求
  • 咨询网站 模板水处理设备网站建设
  • 为什么在百度搜不到我的网站网站搭建哪里找最好
  • 校园网站建设的优点视频直播网站开发运营步骤
  • 规划案例网站公司注册资金实缴和认缴有什么区别
  • 上海浦东建筑建设网站产品设计工具
  • 韦恩图在线制作网站做服装必须看的十大网站
  • 企业网站建站 费用建设网站科目
  • 个人网站页脚设计深圳网站建设公司官网
  • 上海品牌网站设计设计素材网站照片
  • 企业网站推广方案策划江西最新新闻事件
  • 做网站入什么科目网站分享链接怎么做的
  • 知知网站推荐做网站 售后服务里都写啥
  • 站长收录平台网站后台图片编辑器
  • 网站开发字体选择服装行业做推广网站
  • 先做网站还是先备案网站项目建设策划方案
  • 南京响应式网站建设微网站建设讯息
  • 网站建设 高端 北京mip wordpress模板
  • 网站运营推广网站的后台是怎么做的
  • 如何做专业的模板下载网站wordpress 淘客
  • wordpress 编写文章windows优化大师怎么彻底删除
  • 深圳网站建设推选上榜网络网站开发上海工资
  • 湟源县网站建设asp个人网站下载