.Net Core和flask跨域设置,允许所有Origin接受和发送Cookie

前言:自己比较小白,本文中有很多不对的地方欢迎指正

自己以前用python的flask框架写后端程序,在实现跨域时安装flask_cors,然后如下:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

//......

这样的话就可以实现跨域了,且所有的Origin都可以对其发送请求,例如www.baidu.com可以向自己的127.0.0.1:5000的flask程序发送请求,这种跨域方式中,如果前端发送请求时不带上cookie,那么在向前端返回数据时就可以使用

from flask import jsonfiy

@app.route('/../')
def func():
    //......
    return jsonfiy(Obejct)

来返回数据给前端

但是如果前端发送的请求需要带上cookie 的话,那获取cookie 和 返回数据就需要另一种方式

from flask import request,make_response

@app.route('/.../')
def func():
    cookie = request.cookies.get('key')#获取cookie
    response = make_response(jsonfiy(Object))
    response.set_cookie('key','value',max_age=3600)
    response.headers['Access-Control-Allow-Credentials']='true'#设置响应数据的头部,不然无法将response返回给前端
    return response

至于为什么要这么麻烦,是因为,如果使用flask采用前后端分离的方式进行开发时,就会导致跨域,且flask的通过session进行用户验证的方式也无法使用,表现为:session['key']取值为空,暂时未去深挖原因,预估还是前后端分离的开发模式导致的。


前面说了一大堆,主要是想说明一种情况:跨域可以实现:1.所有的Origin对自己开发的服务器程序发送请求,2.能发送和接收cookie。这两个效果,在进行.Net Core开发后端程序时,也以为也可以很简单的实现这种效果,但是比较麻烦:

一:常规的.Net Core设置跨域方式

 public void ConfigureServices(IServiceCollection services)
{
      //.......
      services.AddControllers();
      services.AddCors(options => { options.AddPolicy("allOrigin", p => { p.AllowAnyOrigin(); }); });//所有Origin可以请求,但是这里p.AllowAnyOrigin()后面不允许加上.AllowCredentials()来达到请求携带cookie的效果,原因如下
      //services.AddCors(options => { options.AddPolicy("allOrigin", p => { p.WithOrigins(["http://www.baidu.com"]).AllowCredentials();}); });//这里可以允许来自http://wwww.baidu.com的携带cookie的请求
      //......
            
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
     if (env.IsDevelopment())
     {
           app.UseDeveloperExceptionPage();
           app.UseCookiePolicy();
           app.UseCors("allOrigin");
      }

      app.UseRouting();

      app.UseAuthorization();

      app.UseEndpoints(endpoints =>
      {
           endpoints.MapControllers();
      });
}

这种跨域方式可以允许所有的Origin对其进行请求,在服务器响应数据中,我们能看到头部的Access-Control-Allow-Origin : *

但是这种方式的跨域不允许发送带有cookie的请求。因为,如果需要请求带有cookie,那么响应头的Access-Control-Allow-Credentials="true",但是在服务器响应时,不允许在Access-Control-Allow-Origin=*时,将Access-Control-Allow-Credentials="true",只能将Access-Control-Allow-Origin设置为某一个特定的Origin时,如:hhtp://www.baidu.com,只有这样才可以将Access-Control-Allow-Credentials="true",从而实现请求接收和发送cookie。

可是又有另外一个问题,当我们并不是企业那样的开发,而只是作业,或者其他不能够明确自己前端的Origin的情况下,怎么办呢,换句话说,该怎么样才能够实现像上面的flask那样的两个效果。

思路是:在.Net 进行跨域处理前,先截获此过程。例如,我从http://www.baidu.com发送一个带cookie的请求,按照正常的流程:

①.Net拿到请求,

②读取startup.cs设置的跨域配置,此时分两种情况:a:p.AllowAnyOrigin().AllowCredentials()(这是错误的写法,虽然想达到允许所有Origin发送携带cookie请求的效果,但是有问题,原因如下),b:p.policy.WithOrigins("http://www.baidu.com").AllowCredentials();

③ 根据前一步的结果进行一系列判定,如果是情况a,在准备将Access-Control-Allow-Credentials设置为true时,发现前者为*,那么此过程报错,拒绝响应。对于情况b,对比后发现请求的Origin在[http://www.baidu.com]之中,那么就将Access-Control-Allow-Origin设置为"http://www.baidu.com",在准备将Access-Control-Allow-Credentials设置为true时,发现前者不为*,那么此过程顺利进行。响应数据给前端

我们能做的就是在第③步前,覆盖.Net判定跨域的函数,但是此时需要对startup.cs的跨域配置修改一下,思路是:将允许跨域的Origin数组设为空,然后在第③步前将请求的Oringin添加进去,这样的话,在第③步判定时请求的Oringin必然存在于p.WithOrigins([string url])中了。

public class WildcardCorsService : CorsService
    {
        public WildcardCorsService(IOptions<CorsOptions> options, ILoggerFactory loggerFactory) : base(options, loggerFactory)
        {
        }

        public override void EvaluateRequest(HttpContext context, CorsPolicy policy, CorsResult result)
        {
            var origin = context.Request.Headers[CorsConstants.Origin];
            policy.Origins.Add(origin);
            result.IsOriginAllowed = true;
            result.AllowedOrigin = origin;
            base.EvaluatePreflightRequest(context, policy, result);
        }

        public override void EvaluatePreflightRequest(HttpContext context, CorsPolicy policy, CorsResult result)
        {
            var origin = context.Request.Headers[CorsConstants.Origin];
            Console.WriteLine(origin);
            policy.Origins.Add(origin);
            base.EvaluatePreflightRequest(context, policy, result);
        }


    }

再然后将其注入到service:

 public void ConfigureServices(IServiceCollection services)
{
      //.......
      services.AddControllers();
      services.AddCors(options => { options.AddPolicy("allOrigin", p => { p.AllowAnyOrigin(); }); });//所有Origin可以请求,但是这里p.AllowAnyOrigin()后面不允许加上.AllowCredentials()来达到请求携带cookie的效果,原因如下
      //services.AddCors(options => { options.AddPolicy("allOrigin", p => { p.policy.WithOrigins("http://www.baidu.com").AllowCredentials();}); });//这里可以允许来自http://wwww.baidu.com的携带cookie的请求

      services.Add(ServiceDescriptor.Transient<ICorsService, WildcardCorsService>());
      //......
            
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
     if (env.IsDevelopment())
     {
           app.UseDeveloperExceptionPage();
           app.UseCookiePolicy();
           app.UseCors("allOrigin");
      }

      app.UseRouting();

      app.UseAuthorization();

      app.UseEndpoints(endpoints =>
      {
           endpoints.MapControllers();
      });
}

然后就大功告成了!!!

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值