我正在try 将我的身份验证内容迁移到Core 2.0,但在使用我自己的身份验证方案时遇到了问题.我在startup中的服务设置如下所示:

var authenticationBuilder = services.AddAuthentication(options =>
{
    options.AddScheme("myauth", builder =>
    {
        builder.HandlerType = typeof(CookieAuthenticationHandler);
    });
})
    .AddCookie();

我在控制器中的登录代码如下所示:

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);

但当我在控制器或动作过滤器中时,我只有一个身份,而不是经过身份验证的身份:

var identity = context.HttpContext.User.Identities.SingleOrDefault(x => x.AuthenticationType == "myauth");

应对这些变化一直很困难,但我猜我正在这样做.我错了.有什么建议吗?

编辑:这里(本质上)有一个干净的应用程序,不会在用户身上产生两组身份.身份:

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:这是为编剧设计的低级方法.

如何在ASP.NET Core 2.0中设置多个身份验证方案?

要注册cookies处理程序,只需执行以下操作:

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(这个巨大重构的全部目的是避免同时拥有多个自动身份验证中间件).

如果您确实需要在2.0中模拟这种行为,您可以编写一个自定义中间件,手动调用AuthenticateAsync()并创建一个ClaimsPrincipal,其中包含您需要的所有标识:

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();
        });

        // ...
    }
}

Asp.net相关问答推荐

AJAX返回未定义、失败

Swashbuckle 通过 .NET 应用程序中的 XML 注释使用格式标识符

为什么 @Html.EditorFor 和 @Html.PasswordFor 在 MVC 中创建不同的样式框?

如何在没有 Select 按钮的情况下在 GridView 中实现全行 Select ?

Server.Transfer 在执行子请求时抛出错误.如何解决?

ASP.NET 在更新面板更新时显示正在加载...消息

从 IIS 7/8 中的静态内容中删除服务器标头

忽略默认文档的表单身份验证

通过 jQuery 调用 ASP.NET 服务器端方法

如何在新实现的接口或基类之间做出决定?

如何以编程方式将标签的前景色设置为其默认值?

解析器错误:无法创建类型

如何防止 XXE 攻击(.NET 中的 XmlDocument)

如何验证用户在 CheckBoxList 中 Select 了至少一个复选框?

如何在 ASP.NET MVC 中设置时区?

如何在实体框架中添加表?

删除 HTML 或 ASPX 扩展

您可以从 web.config 文件中的其他位置提取 log4net AdoNetAppender 的 connectionString 吗?

重新生成designer.cs

System.Web.Caching 还是 System.Runtime.Caching 更适合 .NET 4 Web 应用程序