asp.net core 系列之允许跨域访问(Enable Cross-Origin Requests:CORS)

这篇文章介绍如何允许跨域访问

浏览器安全不允许不同域名的网页之间发送请求。这种限制叫做同源策略(the same-origin policy)。

同源策略可以防止一个恶意的站点读取另一个站点的敏感数据。

有时候,你想允许网站发送跨域的请求到你的应用。

Cross Origin Resource Sharing ( CORS ) :

  • 是一个W3C的标准;即允许放宽同源策略
  • 不是一个安全的功能,CORS 放宽了安全性。允许跨域,会让API更不安全
  • 允许一个服务明确的允许一些跨域请求,而拒绝另外一些
  • 比早些的技术(例如JSONP)更安全,更灵活

1.那么同源指的是什么呢

如果两个URLs是同源的,那么它们有相同的协议,主机(域名),端口

下面两个是同源的URLs:

  • https://example.com/foo.html
  • https://example.com/bar.html

下面的这些相比于前面的两个URL,有不同的源:

  • https://example.net – Different domain 不同的域名
  • https://www.example.com/foo.html – Different subdomain 不同的子域名
  • http://example.com/foo.html – Different scheme  不同的协议
  • https://example.com:9000/foo.html – Different port 不同的端口号

IE浏览器考虑同源问题的时候,不会考虑端口号

2.带策略的CORS 和中间件

CORS中间件处理跨域请求。下面的代码允许指定的源能对整个应用进行跨域请求

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
     //AddCors方法的调用会把CORS服务加到应用的服务容器中(service container);
        services.AddCors(options =>
        {
            options.AddPolicy(MyAllowSpecificOrigins,
            builder =>
            {
                builder.WithOrigins("http://example.com",   //CorsPolicyBuilder方法可以链式调用方法,
                                    "http://www.contoso.com");
            });
        });

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseCors(MyAllowSpecificOrigins);    //这个代码会把CORS策略通过CORS中间件应用到这个应用的所有终端(endpoints);即把跨域作用到整个应用
        //注意:1.UseCors必须在UseMvc之前被调用;2. URL末尾不能加/ ;这个url指的是 builder.WithOrigins(url)中的url

这段代码做了下面的操作

  • 设置策略名为_myAllowSpecificOrigins,这个名字是随意取的
  • 调用UseCors 扩展方法来允许跨域
  • 调用带有lambda表达式的 AddCors 方法。lambda表达式取得一个 CorsPlicyBuild对象,进行一些设置

CorsPolicyBuilder方法可以链式调用方法:

builder.WithOrigins("http://example.com",
                                "http://www.contoso.com")
                                .AllowAnyHeader()
                                .AllowAnyMethod();

测试跨域

3.使用[EnableCors]属性设置允许跨域

[EnableCors]属性提供了另一种方式设置跨域。即可以只设置选择的终端,而不是所有的终端.

这里不同于上面的那种方式,上面的方式是应用的所有终端都会被设置允许跨域;

而这里只是设置了[EnableCors]属性的终端;

使用[EnableCors]来指定默认的策略,而[EnableCors("{Policy String}")] 指定了特定的策略;

[EnableCors]属性应用于:

  • Razor Page PageModel
  • Controller
  • Controller action method

你可以使用[EnableCors]属性应用不同的策略到 controller/page-model/action 中;

当[EnableCors]属性应用到 controller/page-model/action ,并且CORS在中间件被允许了(指【Enable("{Policy String}")】的方式),这两种策略就都被使用了;

不推荐结合使用策略;使用[EnableCors]属性或者中间件,而不是在相同的应用中使用两个

下面的代码给每个方法使用了一种策略

[Route("api/[controller]")]
[ApiController]
public class WidgetController : ControllerBase
{
    // GET api/values
    [EnableCors("AnotherPolicy")]
    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    {
        return new string[] { "green widget", "red widget" };
    }

    // GET api/values/5
    [EnableCors]        // Default policy.
    [HttpGet("{id}")]
    public ActionResult<string> Get(int id)
    {
        switch (id)
        {
            case 1:
                return "green widget";
            case 2:
                return "red widget";
            default:
                return NotFound();
        }
    }
}

下面的代码创建了一个跨越默认策略和一个名字叫“AnotherPolicy”的策略:

public class StartupMultiPolicy
{
    public StartupMultiPolicy(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddDefaultPolicy(
                builder =>
                {
                   
                    builder.WithOrigins("http://example.com",
                                        "http://www.contoso.com");
                });

            options.AddPolicy("AnotherPolicy",
                builder =>
                {
                    builder.WithOrigins("http://www.contoso.com")
                                        .AllowAnyHeader()
                                        .AllowAnyMethod();
                });

        });

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseMvc();
    }
}

另,其实还有[DisableCors]属性可以禁止CORS,这里先暂时不做讲解

...未完,待续

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小海怪python学习

Django学习-第三讲(上) 初识Django 模板

在之前的章节中,视图函数只是直接返回文本,而在实际生产环境中其实很少这样用,因为实际的页面大多是带有样式的HTML代码,这可以让浏览器渲染出非常漂亮的页面。DT...

6020
来自专栏DotNet Core圈圈

.NET Core玩转爬虫系列之借助正则表达式入门篇

模拟登录 -> 模拟发送request请求 -> 取回response数据 -> 提取所需信息并将其进行重新组织 -> 存入DB或文件中 -> 后期处理或展示

9210
来自专栏Jerry的SAP技术分享

UI5按钮渲染原理

To debug how is a button rendered in UI5 I created a project by using SAPUI5 app...

6340
来自专栏小海怪python学习

Django学习-第四讲 Django 模板常用过滤器及模板及结构优化

在模版中,有时候需要对一些数据进行处理以后才能使用。一般在Python中我们是通过函数的形式来完成的。而在模版中,则是通过过滤器来实现的。过滤器使用的是|来使用...

7720
来自专栏蚂蚁开源社区

【技术分享】支持移动手机的刮刮卡效果实现

  ScratchCard是一款支持移动手机的HTML5 canvas刮刮卡JS插件。该刮刮卡JS插件支持移动触摸事件,提供刮卡的回调函数,简单易用,效果非常不...

10220
来自专栏运维之美

每天都在用的浏览器,你知道它是如何工作的吗?

浏览器经历了很多年的发展,浏览器引擎也在不停地迭代和演进。从PC时代到移动端,以独立浏览器的形态还是以系统WebView组件内嵌的形态存在,在互联网的生态系统中...

17620
来自专栏达达前端

微信小程序音乐播放器组件

若本号内容有做得不到位的地方(比如:涉及版权或其他问题),请及时联系我们进行整改即可,会在第一时间进行处理。----

21810
来自专栏sktj

jquery 手风琴效果

<!doctype html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta http-eq...

9620
来自专栏达达前端

微信小程序根据状态换图

若本号内容有做得不到位的地方(比如:涉及版权或其他问题),请及时联系我们进行整改即可,会在第一时间进行处理。----

5120
来自专栏DotNet Core圈圈

分层 Blazor 组件

作为加入单页应用程序 (SPA) 队伍的最新框架,Blazor 有机会在其他框架(如 Angular 和 React)的最佳特性基础之上构建而成。尽管 Blaz...

25310

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励