c# - 带有 Owin 身份验证的单声道

标签 c# authentication mono asp.net-identity owin

我有一个在 Mono 中运行的 Owin 应用程序,我正在尝试让身份验证在其上正常工作。我使用了 this page 上的信息作为开始。我很快意识到 Owin 身份验证使用了一些 Windows 特定的库。 This question不过,有一个解决方法,我认为这就足够了。它不是。

以下代码抛出另一个问题中描述的异常(在问题描述之外的另一个地方(参见代码中的注释))。如果我试图注释掉一些东西来定位关于 Owin 管道的错误异常被抛出(因为依赖)。如果我注释掉足以删除第一个异常再次出现。

有没有人能够在 Mono 的 Owin 中成功设置身份验证(使用 AspNet Identity)?

启动

public void Configure(IAppBuilder app)
{
    // Add the AspNet Identity user manager to the Owin context
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

    // This was the first line to fail, but adding the AesDataProtectorProvider as
    // described in the referred question fixed that
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/login"),
        Provider = new CookieAuthenticationProvider
        {
            OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                validateInterval: TimeSpan.FromMinutes(30),
                regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
        },
        TicketDataFormat = new SecureDataFormat<AuthenticationTicket>(
            DataSerializers.Ticket,
            new AesDataProtectorProvider("myAuthKey"),
            TextEncodings.Base64)
    });

    // This causes an exception complaining that the Windows only assembly
    // DpapiDataProtector can't be loaded, as described in the referred question
    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

    // Set up the custom middleware as described in the first link
    // Something inside this causes other exceptions.
    app.Use(typeof(AuthMiddleware), app, new AuthOptions());
}

AuthMiddleware

public class AuthMiddleware : AuthenticationMiddleware<AuthOptions>
{
    public AuthMiddleware(OwinMiddleware next, IAppBuilder app, AuthOptions options)
        : base(next, options)
    {
        if (string.IsNullOrEmpty(Options.SignInAsAuthenticationType))
        {
            options.SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType();
        }
        if (options.StateDataFormat == null)
        {
            var dataProtector = app.CreateDataProtector(typeof(AuthMiddleware).FullName,
            options.AuthenticationType);
            options.StateDataFormat = new PropertiesDataFormat(dataProtector);
        }
    }

    protected override AuthenticationHandler<AuthOptions> CreateHandler()
    {
        return new AuthHandler();
    }
}

AuthOptions

public class AuthOptions : AuthenticationOptions
{
    public AuthOptions()
        : base("MyApp")
    {
        Description.Caption = "MyApp";
        // Where to redirect requests if not authenticated
        CallbackPath = new PathString("/login");            AuthenticationMode = AuthenticationMode.Passive;
    }

    public PathString CallbackPath { get; set; }
    public string SignInAsAuthenticationType { get; set; }
    public ISecureDataFormat<AuthenticationProperties> StateDataFormat { get; set; }
}

授权处理程序

public class AuthHandler : AuthenticationHandler<AuthOptions>
{
    protected override Task<AuthenticationTicket> AuthenticateCoreAsync()
    {
        var identity = new ClaimsIdentity(Options.SignInAsAuthenticationType);
        var properties = Options.StateDataFormat.Unprotect(Request.Query["state"]);
        return Task.FromResult(new AuthenticationTicket(identity, properties));
    }

    protected override Task ApplyResponseChallengeAsync()
    {
        if (Response.StatusCode == 401)
        {
            var challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
            if (challenge != null)
            {
                var state = challenge.Properties;
                if (string.IsNullOrEmpty(state.RedirectUri))
                {
                    state.RedirectUri = Request.Uri.ToString();
                }
                var stateString = Options.StateDataFormat.Protect(state);
                Response.Redirect(WebUtilities.AddQueryString(Options.CallbackPath.Value, "state", stateString));
            }
        }
        return Task.FromResult<object>(null);
    }

    public override async Task<bool> InvokeAsync()
    {
        Request.Environment.Add("Context", Context);

        // If user is not logged in and tries to access any page that is not in
        // the list of allowed pages, redirect to login page
        if (Context.Authentication.User == null && 
            !Request.Path.ToString().StartsWith("/login"))
        {
            Response.Redirect(Options.CallbackPath.Value);
            return true;
        }

        return false;
    }
}

最佳答案

展示 Mono WebAPI、OAuth2 Bearer token 身份验证、AspNet.Identity + MySQL UserStore 的 GitHub 存储库:

https://github.com/shturm/mono-webapi

enter image description here enter image description here

需要弄清楚的几件事:

  1. AspNet.Identity 是一组接口(interface) (Microsoft.AspNet.Identity.Core) 及其实现 (Microsoft.AspNet.Identity.EntityFramework/Owin ),它粗略地描述了用于在数据库中持久保存帐户的存储库模式
  2. AspNet.Identity 不进行身份验证/授权。它在处理密码的同时创建、保存、更新、删除用户。
  3. AspNet.Identity 使用的主要类是 UserManager(来自 Microsoft.AspNet.Identity.Core)和 SignInManger(来自 Microsoft.AspNet.Identity.Owin)。 SignInManager 不是执行任何类型的 OWIN 身份验证所必需的。
  4. 您发布的代码与 Microsoft.Owin 严格相关,与 AspNet.Identity 无关,ApplicationUserManager 除外/strong> 在 Visual Studio 模板中扩展 Microsoft.AspNet.Identity.UserManager

关于c# - 带有 Owin 身份验证的单声道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37012143/

相关文章:

c# - 在模拟对数据库的 WCF 调用时遇到问题,显示 domain\Machine$ 登录失败

authentication - 使用 gRPC 实现用户身份验证

node.js - Express.js 和请求 : Headers unexpectedly reset themselves

.net - Mono 可以在 IIS 7 下运行吗?

c# - MonoDevelop、linux、Ubuntu 18.04 Mint、ConsoleApplication 控制台不弹出

c# - 类析构问题

c# - SWIG 中的委托(delegate) - C#

linux - 单声道 : Is it possible to host a web/wcf service from console application?

c# - 检测 WebRequest 的 HTTP 代理错误

authentication - Kafka SASL Zookeeper 身份验证