如何在 ASP.NET Core 2.0 中设置多个身份验证方案?
我正在尝试将我的身份验证内容迁移到 Core 2.0,但在使用我自己的身份验证方案时遇到了问题.我在启动时的服务设置如下所示:
I'm trying to migrate my auth stuff to Core 2.0 and having an issue using my own authentication scheme. My service setup in startup looks like this:
var authenticationBuilder = services.AddAuthentication(options =>
{
options.AddScheme("myauth", builder =>
{
builder.HandlerType = typeof(CookieAuthenticationHandler);
});
})
.AddCookie();
我在控制器中的登录代码如下所示:
My login code in the controller looks like this:
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.Name)
};
var props = new AuthenticationProperties
{
IsPersistent = persistCookie,
ExpiresUtc = DateTime.UtcNow.AddYears(1)
};
var id = new ClaimsIdentity(claims);
await HttpContext.SignInAsync("myauth", new ClaimsPrincipal(id), props);
但是当我在控制器或动作过滤器中时,我只有一个身份,而且它不是一个经过身份验证的身份:
But when I'm in a controller or action filter, I only have one identity, and it's not an authenticated one:
var identity = context.HttpContext.User.Identities.SingleOrDefault(x => x.AuthenticationType == "myauth");
浏览这些更改很困难,但我猜我在做 .AddScheme 错误.有什么建议吗?
Navigating these changes has been difficult, but I'm guessing that I'm doing .AddScheme wrong. Any suggestions?
这是(基本上)一个干净的应用程序,它不会在 User.Identies 上产生两组身份:
Here's (essentially) a clean app that results not in two sets of Identities on User.Identies:
namespace WebApplication1.Controllers
{
public class Testy : Controller
{
public IActionResult Index()
{
var i = HttpContext.User.Identities;
return Content("index");
}
public async Task<IActionResult> In1()
{
var claims = new List<Claim> { new Claim(ClaimTypes.Name, "In1 name") };
var props = new AuthenticationProperties { IsPersistent = true, ExpiresUtc = DateTime.UtcNow.AddYears(1) };
var id = new ClaimsIdentity(claims);
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(id), props);
return Content("In1");
}
public async Task<IActionResult> In2()
{
var claims = new List<Claim> { new Claim(ClaimTypes.Name, "a2 name") };
var props = new AuthenticationProperties { IsPersistent = true, ExpiresUtc = DateTime.UtcNow.AddYears(1) };
var id = new ClaimsIdentity(claims);
await HttpContext.SignInAsync("a2", new ClaimsPrincipal(id), props);
return Content("In2");
}
public async Task<IActionResult> Out1()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return Content("Out1");
}
public async Task<IActionResult> Out2()
{
await HttpContext.SignOutAsync("a2");
return Content("Out2");
}
}
}
和启动:
namespace WebApplication1
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie("a2");
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
浏览这些更改很困难,但我猜我在做 .AddScheme 错误.
Navigating these changes has been difficult, but I'm guessing that I'm doing .AddScheme wrong.
不要使用 AddScheme
:它是为处理程序编写者设计的低级方法.
Don't use the AddScheme
: it's a low-level method designed for handlers writers.
如何在 ASP.NET Core 2.0 中设置多个身份验证方案?
How do I setup multiple auth schemes in ASP.NET Core 2.0?
要注册 cookie 处理程序,只需执行以下操作:
To register the cookies handler, simply do:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultScheme = "myauth1";
})
.AddCookie("myauth1");
.AddCookie("myauth2");
}
public void Configure(IApplicationBuilder app)
{
app.UseAuthentication();
// ...
}
}
需要注意的是,您不能像在 1.x 中那样注册多个默认方案(这一巨大重构的重点是避免同时拥有多个自动身份验证中间件).
It's important to note that you can't register multiple default schemes like you could in 1.x (the whole point of this huge refactoring is to avoid having multiple automatic authentication middleware at the same time).
如果您绝对需要在 2.0 中模拟此行为,您可以编写一个自定义中间件,手动调用 AuthenticateAsync()
并创建一个包含您需要的所有身份的 ClaimsPrincipal
:
If you absolutely need to emulate this behavior in 2.0, you can write a custom middleware that manually calls AuthenticateAsync()
and creates a ClaimsPrincipal
containing all the identities you need:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultScheme = "myauth1";
})
.AddCookie("myauth1");
.AddCookie("myauth2");
}
public void Configure(IApplicationBuilder app)
{
app.UseAuthentication();
app.Use(async (context, next) =>
{
var principal = new ClaimsPrincipal();
var result1 = await context.AuthenticateAsync("myauth1");
if (result1?.Principal != null)
{
principal.AddIdentities(result1.Principal.Identities);
}
var result2 = await context.AuthenticateAsync("myauth2");
if (result2?.Principal != null)
{
principal.AddIdentities(result2.Principal.Identities);
}
context.User = principal;
await next();
});
// ...
}
}