简体   繁体   English

使用 cookie 身份验证的 ASP.NET Core 2.0 自定义中间件

[英]ASP.NET Core 2.0 custom middleware using cookie authentication

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.我在引号中这么说是因为从技术上讲,用户在访问应用程序之前已通过身份验证,如果是这样,则 userId 将存在于请求标头中。

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.我需要做的是找出一种方法来查询数据库并根据该 Id 获取其他用户信息,并设置 HttpContext.User 对象,以便它可以在应用程序中轻松使用。

The route I am taking now involves using Cookie Authentication without ASP.NET Core Identity.我现在采取的路线涉及使用没有 ASP.NET Core Identity 的 Cookie 身份验证。 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.我将这个想法与自定义中间件相结合,该中间件将为用户查询数据库,从 db 字段填充 Claims,并使用 context.SignInAsync 创建 cookie。 I place this middleware before app.UseAuthentication().我把这个中间件放在 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.问题是在第一次请求时没有设置 .User 对象,因为 SignIn 方法似乎只创建了 cookie 而没有设置 .User 对象。 The Authentication middleware doesn't yet see the cookie because it does not exist on first request.身份验证中间件还没有看到 cookie,因为它在第一次请求时不存在。

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.也许我做错了,或者这种技术很好,但我错过了让它工作所需的东西。

in Startup.cs:在 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?}");
        });
    }

custom Middleware:自定义中间件:

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

Short answer : you should use a custom AuthorizationHandler to authenticate & retrieve claims.简短回答:您应该使用自定义AuthorizationHandler来验证和检索声明。

Long answer : With ASP.NET CORE you should walk away from authentication middleware.长答案:使用 ASP.NET CORE,您应该远离身份验证中间件。 Instead you should use an AuthenticationHandler microsoft相反,您应该使用 AuthenticationHandler microsoft

To create a custom Authentication handler, you will need to create a new class inheriting from AuthenticationHandler<TOption> .要创建自定义身份验证处理程序,您需要创建一个继承自AuthenticationHandler<TOption>的新类。 TOption is a simple class used to pass parameters to your handler. TOption是一个简单的类,用于将参数传递给您的处理程序。

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...");
    }
}

Then you will need to implement the HandleAuthenticateAsync method.然后您将需要实现 HandleAuthenticateAsync 方法。 It will be called by the Auth middleware when necessary: Auth 中间件会在必要时调用它:

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

Claims returned by this method will be available through the HttpContext.User object.此方法返回的声明将通过 HttpContext.User 对象可用。

Once that done, you will need to add your scheme to the authentication builder.完成后,您需要将您的方案添加到身份验证构建器。

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

Don't forget to add in Startup.cs / Configure methods the following code line不要忘记在 Startup.cs / Configure 方法中添加以下代码行

 app.UseAuthentication();

Finally, you will need to add the Authorize attribute on all classes/methods you want to secure最后,您需要在要保护的所有类/方法上添加 Authorize 属性

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

OR

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

EDIT: 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让我们考虑定义两个身份验证方案 - 基于 Cookie 的称为 CookieScheme - AutoSignInScheme:按照上述步骤创建相应的处理程序

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

Then you will need to add the AccountController然后你需要添加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);
    }
 }

In your Startup.cs, add the following lines:在您的 Startup.cs 中,添加以下几行:

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

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!.然后从您的数据库中检索声明,存储在 cookie 中,用户最终被重定向到他的初始目的地!。

Seb塞伯

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 ASP.NET Core 2.0身份验证中间件 - ASP.NET Core 2.0 authentication middleware 在ASP.NET Core中使用授权属性和自定义Cookie身份验证 - Using the Authorize Attribute with Custom Cookie Authentication in ASP.NET Core 如何从ASP.NET Core 2.0中的自定义中间件请求身份验证 - How to request authentication from custom middleware in ASP.NET Core 2.0 ASP.NET Core 2.0 Preview 1:如何使用自定义登录路径设置Cookie身份验证 - ASP.NET Core 2.0 Preview 1: How to set up Cookie Authentication with custom login path 从ASP.NET Core 1.1 MVC迁移到2.0后,自定义cookie身份验证无法正常工作 - Custom cookie authentication not working after migration from ASP.NET Core 1.1 MVC to 2.0 未设置 ASP.NET Core 2.0 身份验证 Cookie - ASP.NET Core 2.0 Authentication Cookie not set Asp.Net Core 2.0 Cookie身份验证在时间之前到期 - Asp.Net Core 2.0 Cookie Authentication Expires Before Time ASP.Net core 2.0 Web API中的Cookie身份验证 - Cookie authentication in ASP.Net core 2.0 Web API 使用Azure AD OpenIdConnect和自定义中间件的ASP NET Core身份验证中的Cookie到期 - Cookie expiry in ASP NET Core Authentication using Azure AD OpenIdConnect and custom middleware 身份验证后,如何在ASP.Net Core中由OpenIdConnect中间件生成的身份验证cookie中添加自定义声明? - How do I add a custom claim to authentication cookie generated by OpenIdConnect middleware in ASP.Net Core after authentication?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM