首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >定制OWIN/Katana UserManager工厂行为

定制OWIN/Katana UserManager工厂行为
EN

Stack Overflow用户
提问于 2015-01-07 17:22:52
回答 1查看 5.3K关注 0票数 5

有许多在线示例使用OWIN/Katana基于ausername/password组合在数据库中查找用户,并生成索赔主体,例如.

代码语言:javascript
复制
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
// generate claims here...

如果您正在创建一个新的应用程序,并且希望实体框架( Entity )来做这些肮脏的工作,这是很好的。但是,我有一个有八年历史的单一网站,它刚刚被更新为使用基于索赔的身份验证。我们的数据库命中是通过DAL/SQL手动完成的,然后从那里生成ClaimsIdentity。

有些人认为OWIN比我们的手工方法更容易使用,但我想从使用它的人那里得到一些输入。

是否有可能改变UserManager工厂根据他们的凭据查找用户的方式?或者,还有别的方法我错过了吗?我可以在网上找到的所有示例似乎都使用了让实体框架创建数据库和管理搜索的样板方法。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-01-08 18:34:24

我想说,ASP.NET身份有点过于复杂了。

2014年8月,他们发布了新版2.1,情况又发生了变化。

首先,让我们摆脱EntityFramework

代码语言:javascript
复制
Uninstall-Package Microsoft.AspNet.Identity.EntityFramework

现在,我们实现了实现接口(Microsoft.AspNet.Identity):的User的定义。

代码语言:javascript
复制
public class User: IUser<int>
{
    public User()
    {
        this.Roles = new List<string>();
        this.Claims = new List<UserClaim>();
    }

    public User(string userName)
        : this()
    {
        this.UserName = userName;
    }

    public User(int id, string userName): this()
    {
        this.Id = Id;
        this.UserName = userName;
    }

    public int Id { get; set; }
    public string UserName { get; set; }
    public string PasswordHash { get; set; }

    public bool LockoutEnabled { get; set; }
    public DateTime? LockoutEndDateUtc { get; set; }
    public bool TwoFactorEnabled { get; set; }

    public IList<string> Roles { get; private set; }
    public IList<UserClaim> Claims { get; private set; }
}

如您所见,我已经定义了我的Id (int)的类型。

然后,您必须定义您的自定义UserManager,从Microsoft.AspNet.Identity.UserManager继承,指定用户类型和键类型。

代码语言:javascript
复制
public class UserManager : UserManager<User, int>
{
    public UserManager(IUserStore<User, int> store): base(store)
    {
        this.UserLockoutEnabledByDefault = false;
        // this.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(10);
        // this.MaxFailedAccessAttemptsBeforeLockout = 10;
        this.UserValidator = new UserValidator<User, int>(this)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = false
        };

        // Configure validation logic for passwords
        this.PasswordValidator = new PasswordValidator
        {
            RequiredLength = 4,
            RequireNonLetterOrDigit = false,
            RequireDigit = false,
            RequireLowercase = false,
            RequireUppercase = false,
        };
    }
}

我已经在这里实现了我的验证规则,但是如果你愿意的话,你可以把它放在外面。

(IUserStore). UserManager需要一个UserStore

您将在这里定义您的DB逻辑。有几个接口需要实现。不过,并不是所有这些都是强制性的。

代码语言:javascript
复制
public class UserStore : 
    IUserStore<User, int>, 
    IUserPasswordStore<User, int>, 
    IUserLockoutStore<User, int>, 
    IUserTwoFactorStore<User, int>,
    IUserRoleStore<User, int>,
    IUserClaimStore<User, int>
{

    // You can inject connection string or db session
    public UserStore()
    {
    }

}

我还没有包括每个接口的所有方法。完成之后,您将能够编写新用户:

代码语言:javascript
复制
public System.Threading.Tasks.Task CreateAsync(User user)
{
}

通过Id获取它:

代码语言:javascript
复制
public System.Threading.Tasks.Task<User> FindByIdAsync(int userId)
{
}

诸若此类。

然后,您需要定义从SignInManager继承的Microsoft.AspNet.Identity.Owin.SignInManager

代码语言:javascript
复制
public class SignInManager: SignInManager<User, int>
{
    public SignInManager(UserManager userManager, IAuthenticationManager authenticationManager): base(userManager, authenticationManager)
    {
    }

    public override Task SignInAsync(User user, bool isPersistent, bool rememberBrowser)
    {
        return base.SignInAsync(user, isPersistent, rememberBrowser);
    }
}

我只实现了SignInAsync:它将生成一个ClaimsIdentity

差不多就是这样。

现在,在Startup类中,您必须告诉Owin如何创建UserManagerSignInManager

代码语言:javascript
复制
app.CreatePerOwinContext<Custom.Identity.UserManager>(() => new Custom.Identity.UserManager(new Custom.Identity.UserStore()));
// app.CreatePerOwinContext<Custom.Identity.RoleManager>(() => new Custom.Identity.RoleManager(new Custom.Identity.RoleStore()));
app.CreatePerOwinContext<Custom.Identity.SignInService>((options, context) => new Custom.Identity.SignInService(context.GetUserManager<Custom.Identity.UserManager>(), context.Authentication));

我没有使用默认模板中的工厂,因为我希望保持尽可能简单。

并使应用程序能够使用cookie:

代码语言:javascript
复制
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/Account/Login"),
        Provider = new CookieAuthenticationProvider
        {
         // Enables the application to validate the security stamp when the user logs in.
         // This is a security feature which is used when you change a password or add an external login to your account.  
         OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<Custom.Identity.UserManager, Custom.Identity.User, int>(
         validateInterval: TimeSpan.FromMinutes(30),
         regenerateIdentityCallback: (manager, user) =>
         {
        var userIdentity = manager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
                return (userIdentity);
    },
        getUserIdCallback: (id) => (Int32.Parse(id.GetUserId()))
        )}
}); 

现在,在您的帐户控制器(或负责登录的控制器)中,您必须获得UserManagerSignInManager

代码语言:javascript
复制
public Custom.Identity.SignInManager SignInManager
{
    get
    {
    return HttpContext.GetOwinContext().Get<Custom.Identity.SignInManager>();
    }
}

public Custom.Identity.UserManager UserManager
{
    get
    {
    return HttpContext.GetOwinContext().GetUserManager<Custom.Identity.UserManager>();
    }
}

您将使用SignInManager进行登录:

代码语言:javascript
复制
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);

以及创建用户的UserManager,添加角色和声明:

代码语言:javascript
复制
if (ModelState.IsValid)
{
        var user = new Custom.Identity.User() { UserName = model.Email };

        var result = await UserManager.CreateAsync(user, model.Password);
        if (result.Succeeded)
    {
        // await UserManager.AddToRoleAsync(user.Id, "Administrators");
                // await UserManager.AddClaimAsync(user.Id, new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Country, "England"));

                await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);

        return RedirectToAction("Index", "Home");
    }
        AddErrors(result);
}

似乎很复杂..。而且它是..。有点。

如果你想读更多关于它的文章,有一个很好的解释这里这里

如果您想运行一些代码并查看它是如何工作的,我已经将一些与代码一起工作的比基 (因为我不想浪费太多时间来定义表和类似的东西)。

如果您有机会从github下载我的代码,您会注意到我创建了一个次要项目(Custom.Identity),在这里我保存了所有ASP.NET Identity内容。

您需要的唯一nuget包是:

  1. Microsoft.AspNet.Identity.Core
  2. Microsoft.AspNet.Identity.Owin
票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27825001

复制
相关文章

相似问题

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