cookies - .NET Core 2.0 Cookie 事件 OnRedirectToLogin

标签 cookies asp.net-core-2.0

如何将中间件应用于 Cookie 选项中的 OnRedirectToLogin 事件(以便我可以使用依赖项注入(inject)),或者如何从 RedirectContext 检索 actionContext?我尝试过搜索文档或示例,但很难找到,而且我还没有看到任何解释或定义如何的示例。这可能吗?

我的 Startup.cs

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                .AddCookie(o =>
                {
                    o.AccessDeniedPath = new PathString("/Error/AccessDenied");
                    o.LoginPath = new PathString("/Account/Login/");
                    o.Cookie.Path = "/";
                    o.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
                    o.Cookie.HttpOnly = true;
                    o.LogoutPath = new PathString("/Account/Logout/");
                    o.Events.OnRedirectToLogin = (context) =>
                    {
                        var routeData = context.HttpContext.GetRouteData();
                        RouteValueDictionary routeValues = new RouteValueDictionary();
                        if (routeData != null) routeValues.Add("lang", routeData.Values["lang"]);
                        Uri uri = new Uri(context.RedirectUri);
                        string returnUrl = HttpUtility.ParseQueryString(uri.Query)[context.Options.ReturnUrlParameter];
                        string focustab = "";
                        context.Request.Query.ToList().ForEach(x =>
                        {
                            if (x.Key == "id") routeValues.Add("id", x.Value.FirstOrDefault());
                            if (x.Key == "values") routeValues.Add("values", x.Value.FirstOrDefault());

                        });

                        routeValues.Add(context.Options.ReturnUrlParameter, returnUrl + focustab);

                        //context here is a redirect context, how can i get the action context to create a new Action as what UrlHelper is expecting
                        context.RedirectUri = new UrlHelper(context).Action("login", "account", routeValues);
                        return Task.CompletedTask;
                    };
                });

提前致谢。

最佳答案

我能够让它按照我想要的方式工作,所以我发布了我的答案,以防其他人遇到这个问题。借助本文档:Use cookie authentication without ASP.NET Core Identity 。我实现了 CustomCookieAuthenticationEvents 并将其转换为 Cookie 事件的类型。

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(o =>
    {
        o.AccessDeniedPath = new PathString("/Error/AccessDenied");
        o.LoginPath = new PathString("/Account/Login/");
        o.Cookie.Path = "/";
        o.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
        o.Cookie.HttpOnly = true;
        o.LogoutPath = new PathString("/Account/Logout/");
        //This line here
        o.EventsType = typeof(CustomCookieAuthenticationEvents);
    });

//register the IActionContextAccessor so that I can inject into my CustomCookieAuthenticationEvents constructor
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

然后在该自定义类中,我能够注入(inject) IUrlHelperFactoryIActionContextAccessor,这有助于我为当前操作创建新的 UrlHelper

public class CustomCookieAuthenticationEvents : CookieAuthenticationEvents
{
    private IUrlHelperFactory _helper;
    private IActionContextAccessor _accessor;
    public CustomCookieAuthenticationEvents(IUrlHelperFactory helper, IActionContextAccessor accessor)
    {
        _helper = helper;
        _accessor = accessor;
    }
    public override Task RedirectToLogin(RedirectContext<CookieAuthenticationOptions> context)
    {
        var routeData = context.Request.HttpContext.GetRouteData();
        RouteValueDictionary routeValues = new RouteValueDictionary();
        //Create new routeValues based on routeData above
        ... code removed for brevity
        Uri uri = new Uri(context.RedirectUri);
        string returnUrl = HttpUtility.ParseQueryString(uri.Query)[context.Options.ReturnUrlParameter];

        routeValues.Add(context.Options.ReturnUrlParameter, returnUrl + focustab);
        var urlHelper = _helper.GetUrlHelper(_accessor.ActionContext);
        context.RedirectUri = UrlHelperExtensions.Action(urlHelper, "login", "account", routeValues);
        return base.RedirectToLogin(context);
    }
}

这允许我修改“重定向到登录”请求上的查询字符串和 returnUrl 参数。我的要求是在第一次登录请求时删除特定的查询字符串值,这使我能够满足该需求。

评论中指出ActionContext在.net Core 3.1中为null。我创建了一个新的.net core 3.1项目,这是确保ActionContext不为null的新代码。尚未完全测试,只是确保注入(inject) IActionContextAccessor 的 ActionContext 不为 null。

这里要记住的主要事情是 IActionContextAccessor 与 MVC 管道一起工作。这意味着我们必须更改 .net core 3.1 模板才能使用 MVC。 CustomCookieAuthenticationEvents 不会改变。

新建 Startup.cs

public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc(m =>
        {
            m.EnableEndpointRouting = false;
        });
        //register the IActionContextAccessor so that I can inject into my CustomCookieAuthenticationEvents constructor
        services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
        services.AddScoped<CustomCookieAuthenticationEvents>();
        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie(o =>
        {
            o.AccessDeniedPath = new PathString("/Error/AccessDenied");
            o.LoginPath = new PathString("/Account/Login/");
            o.Cookie.Path = "/";
            o.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
            o.Cookie.HttpOnly = true;
            o.LogoutPath = new PathString("/Account/Logout/");
            //This line here
            o.EventsType = typeof(CustomCookieAuthenticationEvents);
        });

    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        //app.UseRouting();

        app.UseAuthorization();

        app.UseMvcWithDefaultRoute();

        //app.UseEndpoints(endpoints =>
        //{
        //    endpoints.MapControllerRoute(
        //        name: "default",
        //        pattern: "{controller=Home}/{action=Index}/{id?}");
        //});
    }

关于cookies - .NET Core 2.0 Cookie 事件 OnRedirectToLogin,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48568055/

相关文章:

javascript - 使用POST请求登录时读取服务器发送的cookie

javascript - 客户端数据本地存储

azure - 使用 .net core 删除 Azure Active Directory 上所需的身份验证弹出窗口

authentication - 将 azure AD 身份验证与 asp.net core 身份个人帐户集成

c# - 当 ASP.NET Core 应用程序关闭时,如何正确安全地处理在容器中注册的单例实例

azure - 使用 header 而不是 Cookie 定位特定的 Azure Web 应用程序实例

.net - ASP.Net 表单例份验证 10 分钟后注销用户

javascript - 如何使用 jQuery 获取 cookie 列表?

asp.net-core - ASP.NET Core中的项目之间共享配置文件

asp.net-identity - 如何在 Multi-Tenancy 环境中使用 Asp.Net Core Identity