Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net core ASP.NET核心webapi在中间件中设置cookie_Asp.net Core_Cookies_Middleware - Fatal编程技术网

Asp.net core ASP.NET核心webapi在中间件中设置cookie

Asp.net core ASP.NET核心webapi在中间件中设置cookie,asp.net-core,cookies,middleware,Asp.net Core,Cookies,Middleware,我正在尝试在操作执行后设置cookie,努力使其正常工作。如果我从控制器设置cookie,而不是从中间件设置cookie,我就能够看到它。 我已经玩了配置的顺序,什么都没有。 代码示例来自一个干净的webapi创建的项目,因此如果有人想简单地使用它,只需创建一个空webapi,添加CookieSet类并用下面的类替换Startup类(只添加了cookie策略选项) 这是我的中间件 public class CookieSet { private readonly RequestDeleg

我正在尝试在操作执行后设置cookie,努力使其正常工作。如果我从控制器设置cookie,而不是从中间件设置cookie,我就能够看到它。 我已经玩了配置的顺序,什么都没有。 代码示例来自一个干净的webapi创建的项目,因此如果有人想简单地使用它,只需创建一个空webapi,添加CookieSet类并用下面的类替换Startup类(只添加了cookie策略选项)

这是我的中间件

public class CookieSet
{
    private readonly RequestDelegate _next;

    public CookieSet(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        await _next.Invoke(context);
        var cookieOptions = new CookieOptions()
        {
            Path = "/",
            Expires = DateTimeOffset.UtcNow.AddHours(1),
            IsEssential = true,
            HttpOnly = false,
            Secure = false,
        };
        context.Response.Cookies.Append("test", "cookie", cookieOptions);
    }
}
我已经在Cookies上添加了p赋值,并检查了执行是否从未到达那里。Append行它停止了执行,所以发生了一些我无法理解的事情

这是我的创业课程

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

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            options.CheckConsentNeeded = context => false;
            options.MinimumSameSitePolicy = SameSiteMode.None;
            options.HttpOnly = HttpOnlyPolicy.None;
            options.Secure = CookieSecurePolicy.None;
            // you can add more options here and they will be applied to all cookies (middleware and manually created cookies)
        });

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

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseCookiePolicy(new CookiePolicyOptions
        {
            CheckConsentNeeded = c => false,
            HttpOnly = HttpOnlyPolicy.None,
            Secure = CookieSecurePolicy.None,
            MinimumSameSitePolicy = SameSiteMode.None,
        });

        app.UseMiddleware<CookieSet>();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseMvc();
    }
}
公共类启动
{
公共启动(IConfiguration配置)
{
配置=配置;
}
公共IConfiguration配置{get;}
//此方法由运行时调用。请使用此方法将服务添加到容器中。
public void配置服务(IServiceCollection服务)
{
配置(选项=>
{
options.checkApprovered=context=>false;
options.MinimumSameSitePolicy=SameSiteMode.None;
options.HttpOnly=HttpOnlyPolicy.None;
options.Secure=CookieSecurePolicy.None;
//您可以在此处添加更多选项,这些选项将应用于所有cookie(中间件和手动创建的cookie)
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
//此方法由运行时调用。请使用此方法配置HTTP请求管道。
公共无效配置(IApplicationBuilder应用程序,IHostingEnvironment环境)
{
应用程序。使用CookiePolicy(新CookiePolicy选项
{
checkApprovered=c=>false,
HttpOnly=HttpOnlyPolicy.None,
安全=Cookies安全策略。无,
MinimumSameSitePolicy=SameSiteMode.None,
});
app.UseMiddleware();
if(env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}

我已将所有选项设置为最低要求,使用chrome和fiddler进行了测试,什么都没有。

好的,我在自言自语,但这是为了社区

在深入研究AspNetCore代码后,它开始工作了。 基本上,在启动上下文响应时,必须在回调上设置cookie。 下面是实现该技巧的中间件的代码

public class CookieSet
{
    private readonly RequestDelegate _next;
    private readonly ASessionOptions _options;
    private HttpContext _context;
    public CookieSet(RequestDelegate next, IOptions<ASessionOptions> options)
    {
        _next = next;
        _options = options.Value;
    }

    public async Task Invoke(HttpContext context)
    {
        _context = context;
        context.Response.OnStarting(OnStartingCallBack);
        await _next.Invoke(context);
    }

    private Task OnStartingCallBack()
    {
        var cookieOptions = new CookieOptions()
        {
            Path = "/",
            Expires = DateTimeOffset.UtcNow.AddHours(1),
            IsEssential = true,
            HttpOnly = false,
            Secure = false,
        };
        _context.Response.Cookies.Append("MyCookie", "TheValue", cookieOptions);
        return Task.FromResult(0);
    }
}
.NET 5
这非常有帮助。花几个小时试图理解为什么没有添加cookies。谢谢是的,我也花了很多时间,很高兴能帮上忙;)非常感谢。我认为使用匿名函数可能比在字段中存储http上下文更好。存储上下文可能会导致ObjectDisposedException如果您可以在控制器执行之前设置cookie,则此操作有效。同样适用于.NETCore3.1。我需要一种方法,在执行操作之后立即设置cookie,并注入一些东西来获取一些数据
public class SessionMiddleware
{
    public async Task Invoke(HttpContext context)
    {
        // Removed code here

        if (string.IsNullOrWhiteSpace(sessionKey) || sessionKey.Length != SessionKeyLength)
        {
                        // Removed code here
            var establisher = new SessionEstablisher(context, cookieValue, _options);
            tryEstablishSession = establisher.TryEstablishSession;
            isNewSessionKey = true;
        }

        // Removed code here

        try
        {
            await _next(context);
        }

        // Removed code here
    }

    //Now the inner class

    private class SessionEstablisher
    {
        private readonly HttpContext _context;
        private readonly string _cookieValue;
        private readonly SessionOptions _options;
        private bool _shouldEstablishSession;

        public SessionEstablisher(HttpContext context, string cookieValue, SessionOptions options)
        {
            _context = context;
            _cookieValue = cookieValue;
            _options = options;
            context.Response.OnStarting(OnStartingCallback, state: this);
        }

        private static Task OnStartingCallback(object state)
        {
            var establisher = (SessionEstablisher)state;
            if (establisher._shouldEstablishSession)
            {
                establisher.SetCookie();
            }
            return Task.FromResult(0);
        }

        private void SetCookie()
        {
            var cookieOptions = _options.Cookie.Build(_context);

            var response = _context.Response;
            response.Cookies.Append(_options.Cookie.Name, _cookieValue, cookieOptions);

            var responseHeaders = response.Headers;
            responseHeaders[HeaderNames.CacheControl] = "no-cache";
            responseHeaders[HeaderNames.Pragma] = "no-cache";
            responseHeaders[HeaderNames.Expires] = "-1";
        }

        // Returns true if the session has already been established, or if it still can be because the response has not been sent.
        internal bool TryEstablishSession()
        {
            return (_shouldEstablishSession |= !_context.Response.HasStarted);
        }
    }
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // ........
    app.Use(async (context, next) =>
    {
        var cookieOptions = new CookieOptions()
        {
            Path = "/",
            Expires = DateTimeOffset.UtcNow.AddHours(1),
            IsEssential = true,
            HttpOnly = false,
            Secure = false,
        };
        context.Response.Cookies.Append("MyCookie", "TheValue", cookieOptions);

        await next();
    });
    // ........
}