自定义 OWIN/Katana UserManager 工厂行为

2023-12-15

网上有很多使用 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 工厂根据用户凭据查找用户的方式?或者,还有另一种我错过的方法吗?我可以在网上找到的所有示例似乎都使用让实体框架创建数据库并管理搜索的样板方法。


我想说,ASP.NET Identity 有点过于复杂。
2014 年 8 月,他们宣布了新版本2.1事情又发生了变化。
首先我们要摆脱EntityFramework:

Uninstall-Package Microsoft.AspNet.Identity.EntityFramework

现在我们实现我们自己的定义User实现接口IUser (微软.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).

然后你必须定义你的自定义UserManager继承自Microsoft.AspNet.Identity.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 (用户存储库).

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

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

}

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

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

通过Id获取:

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

等等。

然后你需要定义你的SignInManager继承自Microsoft.AspNet.Identity.Owin.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:它将生成一个声明身份.

差不多就这样了。

现在在你的Startup你必须讲的课Owin如何创建UserManagerSignInManager.

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

现在在您的帐户控制器 - 或负责登录的控制器 - 您将必须获得UserManagerSignInManager:

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

and the 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 and here.

如果你想运行一些代码并看看它是如何工作的,我已经整理了一些code它适用于Biggy(因为我不想浪费太多时间定义表格之类的东西)。

如果您有机会从 github 存储库下载我的代码,您会注意到我创建了一个辅助项目 (Custom.Identity),其中保留了我的所有ASP.NET 身份东西。

唯一的nuget您需要的包有:

  1. Microsoft.AspNet.Identity.Core
  2. 微软.AspNet.Identity.Owin
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自定义 OWIN/Katana UserManager 工厂行为 的相关文章

  • 回发在 Firefox 中对 asp.net(C#) 页面不起作用

    我的 mozilla 火狐浏览器有问题 我正在使用 ASP NET 语言开发一个网站 并且在表单中有一个按钮 当我单击 onclick 属性上的按钮时 我正在调用一个函数 并且该函数执行回发 此场景适用于 Chrome 和 Internet
  • 无法将 null 值插入列...当值不为 null 时

    在我的 C 代码中 我在数据库中有一个插入 但它引发了异常 无法将 NULL 值插入表 Moroccanoil Replicated dbo Boxes 的 BoxID 列 列不允许为空 插入失败 然而 在调试这段代码时 我发现该框实际上不
  • UpdatePanel 中的控件丢失 JQuery 事件

    我有一个位于 updatepanel 控件内的按钮 按钮的单击事件有一个通过 JQuery 为其定义的函数 异步回发完成后 随后单击按钮时 JQuery 事件将无法触发 我需要做什么来纠正此行为并在异步刷新按钮的单击事件后维护 JQuery
  • 将 Sage Line 50 与 Windows 应用程序集成

    我必须将 C Windows 应用程序与 Sage Line 50 集成 将所有发票详细信息从应用程序发送到 Sage 我在 Google 上搜索 大多数地方都说要集成 Sage Line 50 我们需要使用 Sage 开发套件 SDK 但
  • 如何撤消对自我跟踪实体所做的所有更改?

    我有一个客户端应用程序 可以通过 WCF 下载许多 STE 使用 WPF 应用程序 用户可以从列表框中选择一个实体 并通过弹出的用户控件对其进行编辑 由于 UserControl 直接绑定到对象 因此当用户进行更改时 它当然会影响该对象 我
  • 检查域名是否可供购买 - C# [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有什么方法可以检查某个域名是否可以购买 是否有任何图书馆可以做到这一点 THanks 您可以看一下 ht
  • 仅 LINQ to Entities 中的排序输入支持“Skip”方法。必须在方法“Skip”之前调用方法“OrderBy”

    Using 实体框架6 0 2 and NET 4 5 1 in Visual Studio 2013 更新 1 with a DbContext连接到 SQL Server 我有一个很长的过滤器链 我正在根据调用者的期望结果将其应用于查询
  • 在 JavaScript(而非 JQuery)中自动设置电话号码格式

    我发现以下代码用于在 JavaScript 中格式化电话号码这篇文章来自堆栈溢出 https stackoverflow com questions 45471788 formatting the phone number for mult
  • 什么是 IIS 应用程序池?

    应用程序池到底是什么 它的目的是什么 应用程序池允许您将应用程序彼此隔离 即使它们运行在同一台服务器上 这样 如果一个应用程序出现错误 就不会影响其他应用程序 此外 应用程序池允许您分隔需要不同安全级别的不同应用程序 这是一个很好的资源 I
  • 如何去掉所有标签并得到纯文本?

    我必须将用户输入文本存储在我的数据库中HTML and CSS格式 案例是 Rad编辑器 http www telerik com products aspnet ajax editor aspx 用户将文本从 MSWord 复制到此编辑器
  • 如何在 ASP.NET 中动态添加文本框?

    我对我的 asp net 页面有以下要求 用户可以通过单击 添加新类别 超链接在页面 A 上动态添加文本框 他点击页面 A 上的提交按钮并被重定向到页面 B 当他单击此页面中的页面 A 链接时 他添加的文本框应该保留 有人可以帮我解决这个问
  • 在实体框架中不使用 Dispose 或 using()

    我一路上正在编写一个网络应用程序并学习实体框架 如果我做错了什么 我很好奇 我在查询时没有使用过 dispose 或 using 语句 我的存储库示例 public User GetUserById int sessionId var us
  • 找出用户属于哪些组

    我有一个刚刚创建的 Windows 用户帐户 以 XYZ 为例 此 XYZ 属于我在计算机管理 gt 本地用户和组中创建的用户组和自定义组 因此 在属性中我看到该用户属于 2 个组 现在我想获取这些组并显示它们 有什么建议么 我已经这样做了
  • 如何在 IIS 中为我​​的网站关闭自定义错误处理?

    您如何查看 web config 文件 我不知道去哪里关闭自定义错误 帮助 我尝试了命令提示符和java脚本 有人可以帮助我吗 请记住 IS 错误和 asp net 错误是两个不同的事情 对于远程请求 默认情况下 IIS 启用了自定义错误
  • 使用 RsaProtectedConfigurationProvider 进行 Web.Config 加密 - “错误数据”错误

    我正在尝试加密 ASP NET 2 0 Web 应用程序的 Web Config 文件中的连接字符串值 如下所示MSDN 上描述的过程 http msdn microsoft com en us library yxw286t2 VS 80
  • 如何在 Windows Server 上模拟 cron 作业?

    我在 Windows 盒子上运行 NET 我希望每晚午夜运行一个函数 当然 由于 HTTP 无状态并且 Windows 没有 cron job 类型的功能 据我所知 我要么必须每天晚上午夜亲自访问我的网站 要么只是等待用户访问该网站以依赖正
  • LinkBut​​ton 在生产服务器上未触发

    这是一个很好的候选人 适用于我的机器认证计划 http www codinghorror com blog archives 000818 html 我有以下 LinkBut ton 代码
  • ASP.NET 为什么会话超时,sessionstate超时设置

    嘿 我的 web config 中有以下行
  • 如何将隐藏字段从一个页面传递到另一页面?

    我有一个 Net 类库 我想从一次代码隐藏页面传递一个隐藏变量 并在另一个代码隐藏页面中获取它 请注意 我没有任何可以使用表单标签和 get post 方法的设计页面 aspx 页面 我们应该怎么做 注意 我想使用隐藏字段将值从一页传递到另
  • 使用 GROUP 和 SUM 的 LINQ 查询

    请帮助我了解如何使用带有 GROUP 和 SUM 的 LINQ 进行查询 Query the database IEnumerable

随机推荐

  • 无法从Python中的函数增加全局变量[重复]

    这个问题在这里已经有答案了 从这段代码来看 COUNT 0 def increment COUNT COUNT 1 increment 我收到以下错误 Traceback most recent call last File test py
  • 如何在C#中获取外部IP的mac地址

    如何在C 中获取外部IP的mac地址 例如我想找到 204 13 153 34 的mac地址 任何想法和代码片段都受到高度赞赏吗 提前致谢 您应该阅读有关地址解析协议的内容 您无法确定不同网段中机器的 MAC 地址 如果机器恰好位于同一网段
  • 使用 JSON 为数据工厂中的每个循环提供数据

    数据工厂新手 我正在努力解决以下问题 我有一个 Web 活动 它调用 API 并返回以下 JSON ResponseCode 200 ResponseText OK Data ramco purchaseordershipment ramc
  • JavaScript:劫持副本?

    我刚刚在网上阅读 泰晤士报 我想从文章中复制一些文本并将其即时消息发送给朋友 但我注意到当我这样做时 它会自动将链接附加到我复制的文章中 这不是我的 IM 客户端的功能 所以我认为这是由于 Times 网站上的一些 JavaScript 造
  • 未修饰的 JFrame 阴影

    如何向未修饰的 jframe 添加阴影 根据我在网上找到的信息 您也许可以将 jframe 添加到另一个黑色半透明窗口以提供阴影效果 或者以某种方式将类似的内容应用于 JFrame Border loweredBorder new Etch
  • Laravel 5.2 中 Auth::user() 返回 null

    我搜索并发现了如下各种结果 Laravel 5 2 中 auth gt user 为 null and Auth user 返回 null 但是 我的仍然无法工作 Auth user 在控制器中有效 但在模型中无效 它返回null 代码是
  • 与 NSString API 交互时我应该使用哪种 Swift 字符数?

    有时我需要在后台使用依赖于 NSString NSRange 的 API 但我的大部分代码都是用 Swift 编写的 当我需要提供索引 或范围 时 我应该使用哪种 Swift 字符数 例如 给定这个函数 func replace strin
  • XML Inflater 没有看到任何视图?

    首先我应该问是否确实可以做我想做的事情 我有一个自定义的RelativeView 它包含4 个TextView 和一个在xml 布局中定义的按钮
  • Javascript 会出现 CORS 错误,但 Python/PHP 不会出现 CORS 错误

    我正在编写一个小脚本来访问外部 API 以进行工作 我最初是用 Python 做的 一切正常 然后我被要求尝试用 Javascript 来做 现在 我实际上不是程序员 但我确实知道 或相信 Javascript 主要用于客户端 而 PHP
  • 为什么 String.replace 不起作用? [复制]

    这个问题在这里已经有答案了 我现在有点困惑 我尝试过 String test KP 175 105 test replace KP System out println test and got KP 175 105 但是 我想要 175
  • 读取事件参数 AWS lambda

    我有一个 lambda 函数 Node js 4 3 如下所示 exports handler function event context callback console log Received event JSON stringif
  • 根据环境有条件地渲染 Gatsby-config 中的 siteUrl 属性

    我想在我的中设置一个简单的表达式gatsby config js这决定了我是在本地工作还是在生产中工作 以便我可以设置siteUrl财产适当 我的盖茨比配置 带有伪代码 module exports siteMetadata title M
  • 将小型 Oracle 长原始值转换为其他类型

    我有一个 Oracle 表 其中包含 LONG RAW 类型的字段 其中包含 ASCII 字符数据 如何编写查询或视图来将其转换为更容易使用的字符串 FWIW 这些始终是单字节字符 Maybe select to lob long raw
  • 检测文件何时上传到 GAS 中的 Google Drive

    我正在寻找一种在将文件上传到谷歌驱动器时触发 GAS 谷歌应用程序脚本 的方法 有人向我指出了推送通知 API 我无法让它与 GAS 一起工作 StackOverflow 上有很多关于此的问题 但都是 5 年前的事了 从那以后有什么变化吗
  • 此 FORTRAN 代码不应编译。这样做有什么原因吗?

    以下代码可以编译 但我认为不应该编译 正如你所看到的 输出是垃圾 这是一个最小的失败例子 在我从事的一个大型项目中 这个例子让我很痛苦 我的问题是 为什么编译器不抱怨 这是编译器的限制 还是这在某种程度上是 预期的行为 而我错过了一些东西
  • 独角兽陷入循环:刷新宝石列表

    我正在使用 Rails 4 0 0 Ruby 2 3 和 Unicorn 我的应用程序一直运行良好 直到有一天我尝试在 Gemfile 中添加 nem gem 一切都在本地正常运行 但是当我使用 Capistrano 部署到 DO 时 我陷
  • Android 5.x 快门速度

    我正在尝试获取受支持的快门速度参数 但我现在确定如何获取这些范围 对于 ISO 值 String supportIsoValues camParams get iso values 支持的值 逗号分隔的字符串 System out prin
  • Aptana 3 php 无法激活函数链接和变量辅助

    我刚刚升级到 Aptana 3 似乎失去了 Eclipse 中的一些强大功能 到目前为止我不知道如何重新启用它 具体来说 我需要重新打开这两个功能 FileUpload checkForExistingUploadPath somepath
  • Bash 脚本转换日期格式

    我正在寻找替换现有的日期格式 CCYY MM DD with MM DD CCYY使用 shell 脚本将日期格式存储在大文件中 在更改日期格式之前 它应该如下所示 2014 01 31 2014 01 31 更改日期格式后应该如下所示 0
  • 自定义 OWIN/Katana UserManager 工厂行为

    网上有很多使用 OWIN Katana 的示例 可以根据用户名 密码组合在数据库中查找用户并生成声明主体 例如 var userManager context OwinContext GetUserManager