如何将中间件应用于 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) IUrlHelperFactory
和 IActionContextAccessor
,这有助于我为当前操作创建新的 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/