首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >带有Owin认证的Mono

带有Owin认证的Mono
EN

Stack Overflow用户
提问于 2016-05-03 18:50:00
回答 4查看 1.5K关注 0票数 4

我有一个在Mono中运行的Owin应用程序,我正在尝试获得身份验证以使其正常工作。我以此页上的信息作为开始。我很快意识到Owin身份验证使用了一些特定于Windows的库。不过,这个问题有一个解决办法,我认为这就足够了。不是这样的。

下面的代码抛出另一个问题中描述的异常(在问题描述的另一个地方(请参阅代码中的注释)。如果我试图注释掉一些用于定位错误的内容,就会抛出关于Owin管道的异常(因为依赖关系)。如果我的注释足够删除,第一个异常将再次出现。

是否有人能够在Mono中成功地在Owin (使用AspNet标识)中建立身份验证?

启动

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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; }
}

AuthHandler

代码语言:javascript
运行
复制
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;
    }
}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-05-15 21:58:09

显然,上面提交的代码包含了使Owin身份验证工作所必需的更多内容(而且它不适用于Mono)。在研究和尝试了许多排列之后,我相信我现在已经在工作条件下进行了身份验证。我不知道这是否必要,但只要有效.

使用以下设置,未登录的用户只可以访问允许页列表中的页面(由public override async Task<bool> InvokeAsync() in AuthHandler中的方法控制)。在登录页面上,我可以使用ApplicationUserManager在用户中注册。在登录之后,所有由Owin托管的页面都是可访问的。

启动

代码语言:javascript
运行
复制
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

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

app.Use(typeof(AuthMiddleware), app, new AuthOptions());

AuthMiddleware

代码语言:javascript
运行
复制
public class AuthMiddleware : AuthenticationMiddleware<AuthOptions>
{
    public AuthMiddleware(OwinMiddleware next, IAppBuilder app, AuthOptions options)
        : base(next, options)
    {
        if (options.StateDataFormat == null)
        {
            options.StateDataFormat = new PropertiesDataFormat(new AesDataProtectorProvider("myAuthKey"));
        }
    }

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

AuthHandler

代码语言:javascript
运行
复制
public class AuthHandler : AuthenticationHandler<AuthOptions>
{
    protected override Task<AuthenticationTicket> AuthenticateCoreAsync()
    {
        // This method never gets called in the current setup,
        // but it is required because the compilation fails otherwise.
        // Therefore only return an empty object.
        return Task.FromResult<AuthenticationTicket>(null);
    }

    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()
    {
        // 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.
        // Add any additional pages not protected by authentication here
        if (Context.Authentication.User == null && 
            !Request.Path.ToString().StartsWith("/login"))
        {
            Response.Redirect(Options.CallbackPath.Value);
            return true;
        }

        return false;
    }
}
票数 1
EN

Stack Overflow用户

发布于 2016-05-05 20:47:59

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

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

几乎没有什么事情需要弄清楚:

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

Stack Overflow用户

发布于 2016-12-04 20:01:52

Owin中的身份验证使用异步管道,但Mono不支持异步管道。

我对mono https://github.com/mono/mono/pull/3048提出请求。实现了异步web栈的同步执行。

现在,您可以在此修补程序中使用Owin身份验证。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37012143

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档