内容详情 您现在的位置是: 首页> 其他随笔
跨域问题和使用 cookie 的限制
发布时间:2022-06-06 13:01 已围观:1555
摘要跨域问题和使用 cookie 的限制
前言
在我的文章 使用 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 的 SameSite
为 SameSiteMode.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 阮一峰的网络日志
声明:本文内容摘自网络,版权归原作者所有。如有侵权,请联系处理,谢谢~
转发:DvorakChen--https://www.cnblogs.com/dvorakchen/p/16317766.html
赞一个 (343)