使用Cookie身份验证的ASP.NET Core 2.0自定义中间件 [英] ASP.NET Core 2.0 custom middleware using cookie authentication

查看:97
本文介绍了使用Cookie身份验证的ASP.NET Core 2.0自定义中间件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要为我的公司实施自定义身份验证". 我说这是因为引号是因为用户在到达应用程序之前先经过技术验证,如果是这样,则userId将存在于请求标头中.

I need to implement custom "authentication" for my company. I say that in quotes because the user technically gets authenticated before it hits the application and if so, the userId will exist in request headers.

我需要做的是找出一种查询数据库并基于该ID获取其他用户信息的方法,并设置HttpContext.User对象,以便可以在应用程序中轻松使用它.

What I need to do is figure out a way to query the database and get additional user information based on that Id, and set the HttpContext.User object so that it can be used easily within the application.

我现在采用的路由涉及在没有ASP.NET Core身份的情况下使用Cookie身份验证.我将这个想法与自定义中间件结合在一起,该自定义中间件将查询用户数据库,从db字段填充Claims,并使用context.SignInAsync创建cookie.我将此中间件放在app.UseAuthentication()之前.问题是在第一次请求时未设置.User对象,因为似乎SignIn方法仅创建cookie,但未设置.User对象.身份验证中间件尚未看到Cookie,因为它在首次请求时不存在.

The route I am taking now involves using Cookie Authentication without ASP.NET Core Identity. I have combined that idea with custom middleware that will query the database for the user, populate Claims from the db fields, and use the context.SignInAsync to create the cookie. I place this middleware before app.UseAuthentication(). The problem is upon first request the .User object is not set, because it seems the SignIn method only creates the cookie but doesn't set the .User object. The Authentication middleware doesn't yet see the cookie because it does not exist on first request.

有人可以提供任何想法吗?也许我正在做错事,或者这种技术很好,但是我却缺少使它起作用所需的东西.

Could anyone provide any ideas? Maybe I'm going about it wrong, or this technique is fine but I'm missing what I need to make it work.

在Startup.cs中:

in Startup.cs:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();


        services.AddAuthentication("MyAuthenticationCookie")
           .AddCookie("MyAuthenticationCookie");
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseBrowserLink();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();

        app.UseMyUserMiddleware();

        app.UseAuthentication();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }

自定义中间件:

    public class MyUserMiddleware
{
    private readonly RequestDelegate _next;

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

    public Task Invoke(HttpContext context)
    {
        // Sign in user if this auth cookie doesn't exist
        if (context.Request.Cookies[".AspNetCore.MyAuthenticationCookie"] == null)
        {
            // Get user from db - not done

            // Set claims from user object - put in dummy test name for now
            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, "TEST"),

            };

            var claimsIdentity = new ClaimsIdentity(claims, "MyAuthenticationCookie");

            context.SignInAsync("MyAuthenticationCookie", new ClaimsPrincipal(claimsIdentity));
        }

        return this._next(context);
    }
}

public static class MyUserMiddlewareExtensions
{
    public static IApplicationBuilder UseMyUserMiddleware(
        this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<MyUserMiddleware>();
    }
}

推荐答案

简短答案:您应该使用自定义的AuthorizationHandler来验证&检索索赔.

Short answer: you should use a custom AuthorizationHandler to authenticate & retrieve claims.

长答案:使用ASP.NET CORE,您应该远离身份验证中间件.相反,您应该使用AuthenticationHandler microsoft

Long answer: With ASP.NET CORE you should walk away from authentication middleware. Instead you should use an AuthenticationHandler microsoft

要创建自定义的身份验证处理程序,您将需要创建一个继承自AuthenticationHandler<TOption>的新类. TOption是一个简单的类,用于将参数传递给处理程序.

To create a custom Authentication handler, you will need to create a new class inheriting from AuthenticationHandler<TOption>. TOption is a simple class used to pass parameters to your handler.

public class TecMobileOptions : AuthenticationSchemeOptions
{ 
   // Add your options here
}

public class MyNewHandler : AuthenticationHandler<MyOptions>
{
    private readonly ILogger _logger;

    public TecMobileHandler(
        IOptionsMonitor<MyOptions> options,
        ILoggerFactory loggerFactory,
        UrlEncoder encoder,
        ISystemClock clock) : base(options, loggerFactory, encoder, clock)
    {
       // Inject here your DbContext
        _logger = loggerFactory.CreateLogger("name...");
    }
}

然后,您将需要实现HandleAuthenticateAsync方法.必要时,Auth中间件将调用它:

Then you will need to implement the HandleAuthenticateAsync method. It will be called by the Auth middleware when necessary:

    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        var authorization = Request.Headers["UserId"].ToString();
        (...)
        return AuthenticateResult.Success(
            new AuthenticationTicket(**your claims**, Scheme.Name));
    }

此方法返回的声明将通过HttpContext.User对象提供.

Claims returned by this method will be available through the HttpContext.User object.

完成后,您将需要将方案添加到身份验证构建器中.

Once that done, you will need to add your scheme to the authentication builder.

services.AddAuthentication()
   .AddCookie("MyAuthenticationCookie");
   .AddScheme<MyOptions, MyHandler>("MyHandlerName");

不要忘记在Startup.cs/配置方法中添加以下代码行

Don't forget to add in Startup.cs / Configure methods the following code line

 app.UseAuthentication();

最后,您需要在要保护的所有类/方法上添加Authorize属性

Finally, you will need to add the Authorize attribute on all classes/methods you want to secure

[Authorize(AuthenticationSchemes = "MyHandlerName")]
public class MyControllerController : BaseController
{  }

OR

[Authorize(AuthenticationSchemes = "MyHandlerName")]
public IActionResult MyMethod()
{  }

这里的解决方案涵盖了完整的登录过程. 考虑一下您定义了两种身份验证方案 -基于Cookie的称为CookieScheme -AutoSignInScheme:按照上述步骤创建相应的处理程序

Here the solution covering the full login process. Let's consider you define two authentication schemes - Cookie based is called CookieScheme - AutoSignInScheme: create the corresponding handler following the steps above

[Authorize(AuthenticationSchemes = "CookieScheme")]
public class SecuredController : Controller
{
     (...)
}

然后您需要添加AccountController

public class AccountController : Controller
{
    [HttpGet]
    [Authorize(AuthenticationSchemes = "AutoSignInScheme")]
    public async Task<IActionResult> AutoSignIn(string returnUrl)
    {
        await HttpContext.SignInAsync(
           "CookieScheme",
           new ClaimsPrincipal(new ClaimsIdentity(User.Claims, "CookieScheme")));
        return Redirect(returnUrl);
    }
 }

在您的Startup.cs中,添加以下行:

In your Startup.cs, add the following lines:

       services.AddAuthentication()
            .AddCookie("CookieScheme", opts =>
            {
                opts.LoginPath = new PathString("/account/AutoSignIn");
                opts.LogoutPath = ** TODO IF REQUIRED **
                opts.Cookie.Expiration = TimeSpan.FromHours(8);
            })
            .AddScheme<MyOptions, MyHandler>("AutoSignInScheme");

当用户尝试访问您的站点时,他将被重定向到自动登录控制器.然后从您的数据库中检索声明,将其存储在cookie中,并最终将用户重定向到他的初始目的地!.

When the users tries to access your site, he is redirected to the autosignin controller. Claims are then retrieved from your DB, stored in a cookie and the user is finally redirected to his initial destination!.

Seb

这篇关于使用Cookie身份验证的ASP.NET Core 2.0自定义中间件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆