加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net – 自定义OWIN / Katana UserManager工厂行为

发布时间:2020-12-16 03:40:05 所属栏目:asp.Net 来源:网络整理
导读:有很多样本在线使用OWIN / Katana根据用户名/密码组合在数据库中查找用户并生成索赔主体,例如… var userManager = context.OwinContext.GetUserManagerApplicationUserManager();ApplicationUser user = await userManager.FindAsync(context.UserName,cont
有很多样本在线使用OWIN / Katana根据用户名/密码组合在数据库中查找用户并生成索赔主体,例如…

var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
ApplicationUser user = await userManager.FindAsync(context.UserName,context.Password);
// generate claims here...

如果您正在创建一个新的应用程序并希望实体框架执行脏工作,那就没问题.但是,我有一个八年历史的单片网站刚刚更新,使用基于声明的身份验证.我们的数据库命中是通过DAL / SQL手动完成的,然后从那里生成ClaimsIdentity.

有些人建议OWIN比我们的手动方法更容易使用,但我想从那些使用它的人那里得到一些输入.

是否可以根据凭据更改UserManager工厂查找用户的方式?或者,我错过了另一种方法吗?我在网上找到的所有样本似乎都使用样板方法让Entity Framework创建数据库并管理搜索.

解决方法

我会说,ASP.NET身份有点过于复杂.
2014年8月,他们宣布了新版本 2.1,事情再次发生了变化.
首先让我们摆脱EntityFramework:

Uninstall-Package Microsoft.AspNet.Identity.EntityFramework

现在我们实现我们自己定义的User实现接口IUser(Microsoft.AspNet.Identity):

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)的类型.

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

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

我已在此处实施了验证规则,但如果您愿意,可以将其保留在外面.

UserManager需要UserStore(IUserStore).

您将在此处定义数据库逻辑.有几个接口要实现.但并非所有这些都是强制性的.

public class UserStore : 
    IUserStore<User,int>,IUserPasswordStore<User,IUserLockoutStore<User,IUserTwoFactorStore<User,IUserRoleStore<User,IUserClaimStore<User,int>
{

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

}

我没有为每个接口包含所有方法.完成后,您将能够编写新用户:

public System.Threading.Tasks.Task CreateAsync(User user)
{
}

通过Id获取它:

public System.Threading.Tasks.Task<User> FindByIdAsync(int userId)
{
}

等等.

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

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如何创建UserManager和SignInManager.

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:

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

现在在您的帐户控制器 – 或负责登录的控制器 – 您将必须获取UserManager和SignInManager:

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进行登录:

var result = await SignInManager.PasswordSignInAsync(model.Email,model.Password,model.RememberMe,shouldLockout: false);

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

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

这似乎很复杂……而且……有点儿.

如果你想了解更多关于它的信息,可以使用here和here作为一个很好的解释.

如果你想运行一些代码并看看它是如何工作的,我将code与Biggy一起使用(因为我不想浪费很多时间来定义表格和类似的东西).

如果你有机会从github repo下载我的代码,你会发现我已经创建了一个辅助项目(Custom.Identity),我保留了所有的ASP.NET标识.

您需要的唯一nuget包是:

> Microsoft.AspNet.Identity.Core> Microsoft.AspNet.Identity.Owin

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读