前言

在我的文章 使用 cookie 的身份验证和授权 的最后,讲到了跨域问题,这篇文章就简单介绍跨域的相关知识,并说明在 net core 中怎么设置跨域。

使用的版本为 net6,并使用 MiniApi 演示。

XSS 攻击

跨域的由来不得不提到 XSS 攻击。

全名:Cross-site scripting(跨站脚本攻击)。这是一种安全漏洞,攻击者可以利用这种漏洞在网站上注入恶意的客户端代码。若受害者运行这些恶意代码,攻击者就可以突破网站的访问限制并冒充受害者。简单地说,就是我可以在你的网站偷偷上运行我的代码,那有多危险。

为了应对这种情况,便有了浏览器的同源策略。

同源策略

这个策略是由浏览器去实现的,其目的在于限制请求方如何与另一个源的资源进行交互。

“源”你就理解为地址,但它的完整格式由协议、域名、端口组成,如:

https://store.company.com:8000

另一个客户端请求上面的地址,如果协议、域名、端口其中有一个不同,这两个就算两个源,客户端的行为要受到限制。

下表给出了与 URL http://store.company.com/dir/page.html 的源进行对比的示例:

URL 结果 原因
http://store.company.com/dir2/other.html 同源 只有路径不同
http://store.company.com/dir/inner/another.html 同源 只有路径不同
https://store.company.com/secure.html 失败 协议不同
http://store.company.com:81/dir/etc.html 失败 端口不同 ( http:// 默认端口是 80)
http://news.company.com/dir/other.html 失败 主机不同

不同源的请求,就被认为是跨域,是不被允许的。如果发起了跨域了 GET 请求,你可能会在控制台中看到了如下输出:

其原因就是因为跨域了,且服务器没有允许你这个源,所以请求被拒绝了。

而在我们的前后端分离项目中,前端和后端是分别部署在不同的源上的,那么我前端请求后端的数据也会遭受到跨域的限制,那么我们需要放宽这个限制,不然就获取不到数据了。放宽限制,一般是要在后端进行操作,我以 net6 为例子。

net6 配置跨域

在 net6 中放宽我们的跨域限制,需要先配置我们的跨域策略。添加如下代码:

builder.Services.AddCors(options =>
options.AddPolicy(name: "CORS Name", b =>
{
b.WithOrigins("https://example.net");
})
);

使用 AddCors 配置跨域,在参数 options 中,使用 options.AddPolicy 添加一个跨域策略,第一个参数 name,是策略的名字,第二个参数是这个策略的内容。在上面的内容中,使用了 WithOrigins 来配置允许的源。源的最后是没有斜杠的,不可以写成 https://example.net/

接下来,我们的客户端源:https://example.net 在发起 GET 请求的话,就会突破同源的限制,成功请求。

在上面配置了源的情况下,如果使用了 PUT 请求,也会因为跨域请求失败。这是因为跨域还限制了请求方法,默认是支持 GET 和 POST 的,如果要支持其他的方法,也要配置,如下:

builder.Services.AddCors(options =>
options.AddPolicy(name: "CORS Name", b =>
{
b.WithOrigins("https://example.net")
.WithMethods("PUT", "DELETE");
})
);

在上述代码上,我们就支持了 PUT 和 DELETE 请求。此外如果说要允许所有的源、所有方法的话,可以直接使用 .AllowAnyOrigin().AllowAnyMethod()。一般不会这样用,但也说不定,毕竟防呆不防傻。

在中间件中使用 UseCors 扩展方法启用跨域,在参数中指定策略名,顺序必须在 UseRouting 之后,但在 UseAuthorization 之前:

app.UseRouting();
// ...
app.UseCors("CORS Name");
// ...
app.UseAuthorization();

使 cookie 跨域

如果你使用 cookie 来存放我们的凭证信息,且使用的前后端是不同的源,那么还需要做一些配置,来使 cookie 可以跨域。

在跨域配置中使用 .AllowCredentials() 来允许身份凭证信息跨域传递,还需要再身份验证中配置 cookie 的 SameSiteSameSiteMode.None,并且设置 Secure 属性。这样,在不同源也可以接收 cookie。

SameSite 用于限制第三方 cookie,是出于安全考虑,值为 SameSiteMode.None 表示不限制第三方 cookie。

builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
// 配置 cookie
options.Cookie.SameSite = SameSiteMode.None;
}); builder.Services.AddCors(options =>
options.AddPolicy(name: "CORS Name", b =>
{
b.WithOrigins("https://example.net")
.AllowCredentials();
})
);

然后在我们的前端中发起请求,因为是不同源,如果要携带上 cookie,在发起请求时要设置 credentials: "include",以 fetch 为例:

fetch(`https://example.net/logout`, {
method: "post",
credentials: "include",
});

总结

如你所见,使用 cookie 有很多的限制,这些限制的本意是让 cookie 更加安全。而我们为了要让 cookie 跨域,又不得不一点点解除限制,很是难受。

所以不推荐在跨域的情况下使用 cookie 存放身份凭证信息,不安全。

参考资料

Cross-site scripting(跨站脚本攻击) by MDN

浏览器的同源策略 by MDN

在 ASP.NET Core 中启用跨源请求 (CORS) by Microsoft

Cookie 的 SameSite 属性 by 阮一峰的网络日志

跨域问题和使用 cookie 的限制的更多相关文章

  1. Angularjs之如何在跨域请求中传输Cookie

    一般情况我们在使用WebApi之类的技术时,都会遇到跨域的问题,这个只需要在服务端做一下处理即可. 如果这些GET或POST请求不需要传递Cookie数据的话,就没什么问题了,但如果需要,那么会发现 ...

  2. jquery + node 通过 CORS 实现跨域访问,支持cookie和自定义header

    跨域有多种方式,现在的情况看来还是CORS更适合一些,有很多优点,比如浏览器正式支持.支持post.可以控制跨域访问的网站等. 我们来看看node如何实现cors方式的跨域.在网上找到了一些代码,考过 ...

  3. [转] js网络请求跨域问题汇总(携带cookie)

    前端程序使用extjs写,在本地测试,发送请求到服务器时,发现存在跨域的问题,cookie也没有set成功,于是乎在这里整理一下解决过程 由于篇幅较长,不想看解决过程的可以翻到最后看总结1.跨域允许2 ...

  4. Ajax跨域请求中的Cookie问题(默认不带cookie等凭证)

    1.原生Ajax请求方式,设置跨域请求附带详细参数 var xhr = new XMLHttpRequest(); xhr.open("POST", "http://xx ...

  5. XMLHttpRequest.withCredentials 解决跨域请求头无Cookie的问题

    查看原文 XMLHttpRequest.withCredentials  属性是一个Boolean类型,它指示了是否该使用类似cookies,authorization headers(头部授权)或者 ...

  6. 跨域导致无法获取cookie

    首先我用的框架是vue,请求协议用的是ajax,跨域的处理办法是使用了反向代理,在我之前的博文有详细说明,有兴趣的可以去查看下,在做身份认证权限限制的时候,后台有在http-header的respon ...

  7. vue 跨域请求,后端cookie session取不到

    虽然后端设置了可以跨域请求,但是后台设置到cookie中的session取不到!这时候mac电脑自己设置nginx代理! mac电脑系统重装了,记录一下安装nginx的过程: 1.打开终端(cmd) ...

  8. axios 跨域请求允许带cookie,则服务器Access-Control-Allow-Origin应设置为具体域名,否则请求无法获得返回数据

    1.通过允许跨域访问实现了跨域请求,但为了使每个请求带上session信息,我设置了withCredentials ,即: axios.defaults.withCredentials = true ...

  9. 【JavaScript】JS跨域设置和取Cookie

    cookie 是存储于访问者的计算机中的变量.每当同一台计算机通过浏览器请求某个页面时,就会发送这个 cookie.你可以使用 JavaScript 来创建和取回 cookie 的值.本文主要JS怎样 ...

随机推荐

  1. java中Object类是怎么回事,干嘛使的?举例说明!

    Object类的作用:m a r k - t o-        w i n: 在java中,因为所有的类都有共性,所以java的缔造者们把java设计成这样:所有的类都是Object类的直接或间接子 ...

  2. java中什么叫覆盖Override?请给实例

    5.覆盖(Override) 马克-to-win:方法的覆盖(Override)是指子类重写从父类继承来的一个同名方法(参数.返回值也同). 例1.5.1-- class AAAMark_to_win ...

  3. 分库分表实现方式Client和Proxy,性能和维护性该怎么选?

    大家好,我是[架构摆渡人],一只十年的程序猿.这是分库分表系列的第一篇文章,这个系列会给大家分享很多在实际工作中有用的经验,如果有收获,还请分享给更多的朋友. 其实这个系列有录过视频给大家学习,但很多 ...

  4. 面试官:Zookeeper怎么解决读写、双写并发不一致问题,以及共享锁的实现原理?

    哈喽!大家好,我是小奇,一位不靠谱的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 今天清明假期,赶上北京玉渊潭公园 ...

  5. Kubernetes架构-图解

  6. mysql-cluster-gpl-7.5.10-linux-glibc2.12-x86_64.tar.gz (有必要解释一下)

    大部分软件我们接触的时候会发现,起的名称有点怪异,所以我觉得有必要解释一下. 比如: mysql-cluster-gpl-7.5.10-linux-glibc2.12-x86_64.tar.gz 名称 ...

  7. Git原理学习记录

    Git原理学习记录 1.git init git-test ​ git init 实际上就是在特定的目录下创建对应的目录和文件 2.object $ echo "V1" > ...

  8. php实验一专属跳转博文

    今天完成了php关于设计个人博客主页的实验一作业. 这是php实验一作业中博客的跳转链接页.  

  9. Codeforces Round #742 (Div. 2) B. MEXor Mixup

    题目链接 Problem - B - Codeforces 题意: 给出MEX 和 XOR(分别表示1. 本串数不存在的最小非负数  2. 本串数所有数异或后的结果) 求出这串数最少有几个数, 1 ≤ ...

  10. 2021.12.06 P2501 [HAOI2006]数字序列(动态规划+LIS)

    2021.12.06 P2501 [HAOI2006]数字序列(动态规划+LIS) https://www.luogu.com.cn/problem/P2501 题意: 现在我们有一个长度为 n 的整 ...