.Net Core Cors中间件的使用示例
这篇文章给大家介绍.Net Core Cors中间件的使用示例,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。
同源策略和资源跨域共享
1、同源策略
同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。
1.1、目的
主要是为了保证用户信息的安全,防止网站窃取用户数据。假如没有同源策略,可能就会有下面这种情况的发生。用户访问两个网站A/B,并登录了A网站,A网站会在计算机本地存储Cookie或者Token等等,在访问B网站的时候,B网站就可以访问这些本地的存储信息,B网站可以使用用户的Cookie去登录A网站,那这样用户信息就被泄露了。
1.2、限制范围
Cookie、LocalStorage和indexDB无法访问(只有同源的网页才能共享Cookie)
DOM无法获得(父窗口和子窗口的地址是同源的才能获取子窗口的信息)
AJAX请求不能被发送(AJAX请求只能发送给同源的网址)
要知道一点,这些限制其实都是浏览器做的限制。
2、跨域资源共享
跨域资源共享跟同源策略相反。在整个跨域通信过程中,浏览器会自动识别此次请求是否跨域,一旦发现跨域,就自动添加请求头信息(如Origin)或者自动发送一次请求方式为option的预请求。浏览器将CORS请求分为两类:简单请求和非简单请求。
2.1、简单请求
当浏览器的请求方式是Head、Get或者Post,并且HTTP的头信息中不会超出以下字段:
Accept
Accept-Language
Content-Language
Origin
时,浏览器会将该请求定义为简单请求,否则就是非简单请求。当浏览器判断为简单请求后,浏览器会自动再请求报文头中加上Origin字段,表明此次请求来自的地址(协议+域名+端口)。然后服务器需要去判断是否接受这个来源的请求。如果允许服务器端返回的头部中需要有Access-Control-Allow-Origin,其值为请求时Origin字段的值或*(表示接受任意源的请求)。请求头中还会有Access-Control-Allow-Methods表示服务器允许的跨域请求的方式。Access-Control-Allow-Headers表示请求头中允许出现的字段。
2.2、 非简单请求
当浏览器判断为非简单请求后,会发送两次请求,首先浏览器会自动发送一个请求方式为options的请求,并在请求头中
加上Access-Control-Request-Method表示下次请求的方法,
加上Origin表明来源,
加上Access-Control-Request-Headers表示下次请求的请求头中额外的字段。
服务器收到请求后,需要获取这三个请求头中的值,并进行判断,确认是否允许进行跨域。如果服务器返回的请求头中没有任何CORS相关的请求头信息,浏览器会认为不通过预检,也不会进行第二次请求。
服务器如果接受跨域并验证通过了options的请求,会返回Access-Control-Allow-Origin(表明允许跨域请求的源)、Access-Control-Allow-Methods(允许跨域请求的请求方式)、Access-Control-Allow-Headers(允许请求头中包含的额外字段)。然后浏览器才会发送真正的请求。
(第一次options请求)
(第二次请求)
二、服务端实现CORS
在.Net Core Web Api中使用很简单,首先安装包Microsoft.AspNet.WebApi.Cors
,在StartUp中添加下面两句
publicvoidConfigureServices(IServiceCollectionservices) { services.AddMvc(); //添加Cors,并配置CorsPolicy services.AddCors(options=>options.AddPolicy("CorsTest",p=>p.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod())); } publicvoidConfigure(IApplicationBuilderapp,IHostingEnvironmentenv,ILoggerFactoryloggerFactory) { if(env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } //注意UseCors()要在UseMvc()之前 app.UseCors("CorsTest"); app.UseMvc(); }
在使用的时候只需要在Controller或者Action中加上特性[EnableCors("CorsTest")]
[EnableCors("CorsTest")] publicclassValuesController:Controller { privateILogger<ValuesController>_logger; publicValuesController(ILogger<ValuesController>logger) { _logger=logger; } [HttpGet] publicIEnumerable<string>Get() { returnnewstring[]{"value1","value2"}; } }
现在服务端已经配置好了,现在需要通过前端跨域请求
<html> <head> 测试 </head> <body> 测试 </body> </html> <scriptsrc="https://code.jquery.com/jquery-3.3.1.min.js"></script> <scripttype="text/javascript"> $(function(){ $.ajax({ type:"get", url:"http://localhost:7000/api/values", beforeSend:function(request){//在请求报文头中加入Authorization目的是让请求为非简单请求 request.setRequestHeader("Authorization","Bearer071899A00D4D4C5B1C41A6B0211B9399"); }, success:function(result){ alert(result); } },"json"); }); </script>
测试结果如下图:
(options请求)
(第二次请求)
上面配置允许所有的地址请求这个接口,也可以单独配置某个地址。
services.AddCors(options=>options.AddPolicy("CorsTest",p=>p.WithOrigins("http://localhost:8089") .AllowAnyHeader() .AllowAnyMethod()));
三、解析Cors源码
打开CORS源码,主要的是CorsMiddleware、CorsOptions、CorsPolicy、CorsPolicyBuilder、CorsResult、CorsService这几个类。
CorsPolicy:就是我们在Startup中的配置,如允许哪些域名可以跨域请求,允许哪些跨域请求方式,允许哪些额外的请求头,每个配置对应一个名称。
services.AddCors(options => options.AddPolicy("CorsTest", p => p.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()));
CorsOptions:中包含一个字典
IDictionary<string, CorsPolicy> PolicyMap
,一个项目可能有过个Cors配置,所以这个CorsOptions就是通过配置名称管理这些配置的。CorsPolicyBuilder:通过它来构造CorsPolicy。
CorsResult:是验证跨域过程得到的结果。如在第一次Options请求时,客户端发送了Origi:http://localhost:8089,服务器会返回Access-Control-Allow-Origin:http://localhost:8089,服务器验证http://localhost:8089这个域名是否允许跨域,如果允许就将“http://localhost:8089”这个值存储到CorsResult的AllowedHeaders中,在请求(第一次请求)返回的时候将这些加到HTTP请求头中。
CorsMiddleware:Cors中间件类,主要方法就是Invoke,每次HTTP请求都会调用这个方法。
publicasyncTaskInvoke(HttpContextcontext) {//判断HTTP请求头是否有Origin,由此判断是不是跨域请求 if(context.Request.Headers.ContainsKey(CorsConstants.Origin)) { varcorsPolicy=_policy??await_corsPolicyProvider?.GetPolicyAsync(context,_corsPolicyName); if(corsPolicy!=null) { varaccessControlRequestMethod=context.Request.Headers[CorsConstants.AccessControlRequestMethod]; //如果是跨域请求判断是不是第一次Options请求 if(string.Equals(context.Request.Method,CorsConstants.PreflightHttpMethod,StringComparison.OrdinalIgnoreCase) &&!StringValues.IsNullOrEmpty(accessControlRequestMethod)) { //判断是否允许当前请求跨域,根据HttpContext的内容和Cors配置得到CorsResult,然后将CorsResult的内容添加到请求头中(看下面详细解释) ApplyCorsHeaders(context,corsPolicy); context.Response.StatusCode=StatusCodes.Status204NoContent; return; } else {//执行第二次非Options请求 context.Response.OnStarting(state=> { var(httpContext,policy)=(Tuple<HttpContext,CorsPolicy>)state; try { ApplyCorsHeaders(httpContext,policy); } catch(Exceptionexception) { _logger.FailedToSetCorsHeaders(exception); } returnTask.CompletedTask; },Tuple.Create(context,corsPolicy)); } } } await_next(context); } privatevoidApplyCorsHeaders(HttpContextcontext,CorsPolicycorsPolicy) { //通过HTTP上下文请求的数据和Cors配置得到CorsResult 如在第一次Options请求时,客户端发送了Origi:http://localhost:8089,Access-Control-Resquest-Methods:GET 服务器会返回Access-Control-Allow-Origin:http://localhost:8089,Access-Control-Allow-Methods:GET 服务器验证http://localhost:8089这个域名以GET请求方式是否允许跨域, 如果允许就将“http://localhost:8089”这个值存储到CorsResult的AllowedHeaders中 将"GET"存储到CorsResult的AllowedMethods中 varcorsResult=_corsService.EvaluatePolicy(context,corsPolicy); //将CorsResult中的值添加到相应头中的,返回到客户端 _corsService.ApplyResult(corsResult,context.Response); }
关于.Net Core Cors中间件的使用示例就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
推荐阅读
-
在Python中,将K添加到列元组列表中的最小元素
处理数据集涉及识别特定列中的最小值并通过添加常量值(K)来更新它。通过实施优化的解决方案,我们可以有效地执行此操作,这对于数据...
-
使用switch case语句编写的C程序,用于计算几何图形的面积
#includevoidmain(){intfig_code;floatside,base,length,...
-
如何使 C# 代码可重用?
要在C#中使代码可重用,请使用接口。接口定义属性、方法和事件,这些成员是接口的成员。接口只包含成员的声明。派生类负责定义成员。这通...
-
C# 中的覆盖和隐藏有什么区别?
方法隐藏在C#中也称为隐藏。父类的方法可供子类使用,无需在遮蔽中使用override关键字。子类有其自己版本的相同函数。在...
-
在Java中使用示例双倍longValue()函数
Java是一种强大的面向对象语言,可以对各种数据类型进行高度的控制和精确度。其中一种功能是doublelongValue(),...
-
如何在Java中定义JSON字段名称的命名约定?
TheFieldNamingPolicycanbeusedtodefineafewstandardnaming...
-
Servlet中的HttpSession接口
在JavaWeb开发领域,了解HttpSession接口是创建动态和响应式Web应用程序的关键。在本文中,我们将探讨...
-
使用while循环查找自然数之和的Java程序
自然数之和可以使用编程语言中的不同迭代语句来计算。迭代语句是执行一组特定代码行直到循环语句中的条件失败的语句。在本文中,我们将讨论...
-
我们可以将Java数组转换为列表吗?
我们可以使用Arrays.asList()方法轻松地将Java数组转换为List。语法publicstaticLi...
-
Java中如何在不使用任何外部库的情况下读取网页内容?
TheURLclassofthejava.netpackagerepresentsaUniformResour...