AspNet Identity 和 Owin 谁是谁

英文原文:http://tech.trailmax.info/2014/08/aspnet-identity-and-owin-who-is-who/ 

最近我发现Stackoverflow上有一个非常好的问题.提问者问:为什么在调用AuthenticationManager.SignIn后,claim仍然可以被添加到Identity并持久化到cookie里.

示例代码如下所示:

ClaimsIdentity identity = UserManager.CreateIdentity(user,
DefaultAuthenticationTypes.ApplicationCookie );
var claim1 = new Claim(ClaimTypes.Country, "Arctica"); identity.AddClaim(claim1);AuthenticationManager.SignIn(new AuthenticationProperties
{ IsPersistent = true }, identity );
var claim2 = new Claim(ClaimTypes.Country, "Antartica"); identity.AddClaim(claim2);

是的,为什么claim2在cookie已经设置完成后还可用.

在深入研究后,我发现AspNet Identity框架不设置cookie,而OWIN会设置,OWIN是Katana开源项目的一部分.有源码可用是一件好事--你可以发现为什么事情有或没有按你预期的方式工作.

在这个案例里,我花了一些时间探索Katana项目和 AuthenticationManager 工作方式.结果证明SignIn方法不设置cookie.它把Identity对象保存在内存里,直到设置响应cookies的时刻到来,然后claims被转化为一个cookie,所有的事情就这样魔法般地工作着 -)

结果证明Identity框架只处理user持久化,密码哈希,验证密码是否正确,发送密码重置邮件,等等.但是Identity实际上不验证users或创建cookies.而Cookies是被OWIN处理的.

看一下登录的代码:

public async Task SignInAsync(Microsoft.Owin.Security.IAuthenticationManager 
authenticationManager, ApplicationUser applicationUser, bool isPersistent) {authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);ClaimsIdentity identity = await UserManager.CreateIdentityAsync(applicationUser,
DefaultAuthenticationTypes.ApplicationCookie);authenticationManager.SignIn(new Microsoft.Owin.Security.AuthenticationProperties()
{
IsPersistent = isPersistent
}, identity); }

Identity只创建ClaimsIdentity(学习网站 ReferenceSource ),而ClaimsIdentity是.Net framework的一部分,而不是来自于互联网的nuget包.然后这个ClaimsIdentity被传给拥有一个设置cookies回调的OWIN的AuthenticationManager,而AuthenticationManager拥有一个在写响应头时设置cookies的回调.

到目前为止都很好,已有三部分:Identity框架创建一个ClaimsIdentity,OWIN根据这个ClaimsIdentity创建一个cookie,和.Net framework掌控ClaimsIdentity的类.

当在你的类中要访问ClaimsPrincipal.Current时,你只用到.Net framework,不需要用到其它类库,这是非常方便的!

 

默认的Claims

Identity框架为你做了一件很漂亮的事,默认情况下当你登录时,它为一个principal添加了一些claims,如下所示:

  • User.Id:类型为“http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier” 或ClaimTypes.NameIdentifier.

  • Username:类型为“http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name” 或ClaimTypes.Name.

  • "ASP.NET Identity":保存为“http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider“.这在你使用OpenId做验证时非常有用.不过如果只是使用数据库存储users时没什么用.点击查看更多信息.

  • 包含user的安全邮戳的Guid,在Claim中持久化类型为“AspNet.Identity.SecurityStamp“.安全邮戳是user状态的一个主要快照,如果验证的密码/方法,email,等等发生变化,安全邮戳就会发生变化,这允许你通过改变证书实现"在任何地方登出".从Kung的回答中获取更多有关安全邮戳的信息.

  • 最有用的claims是role.所有分配给user的role被保存成ClaimTypes.Role或“http://schemas.microsoft.com/ws/2008/06/identity/claims/role“.所以下次你需要检查当前user的roles,检查这个claims,不会到数据库中查找,这样非常快.实际上,如果你调用ClaimsPrincipal的.IsInRole("RoleName"),框架会进入claims并检查用户是否分配了这个指定值的Role.

你可以在.Net Reference 网站查看这些claim类型,这个列表不是完整的,你可以创建你自己的claim类型--就是一个string.

如果你想添加你自己的owin claim类型,我建议你使用自己的符号,例如:“MyAppplication:GroupId” ,并保持所有的claim类型作为常量在一个类中:

public class MyApplicationClaimTypes
{    
    public string const GroupId = "MyAppplication:GroupId";
public string const PersonId = "MyAppplication:PersonId";
// other claim types

}


这种方式,你总是可以找到claims,并不会与框架中的claim类型冲突,除非你的claims与框架中的claims类型完全一致,例如:ClaimTypes.Email.

 

添加默认的claims

我总是在user登录里,添加user的email到claims列表中,就如最前面示例里的claim1和claim2:

public async Task SignInAsync(IAuthenticationManager authenticationManager,
ApplicationUser applicationUser, bool isPersistent) {authenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie,DefaultAuthenticationTypes.ApplicationCookie);
var identity = await this.CreateIdentityAsync(applicationUser,
DefaultAuthenticationTypes.ApplicationCookie);
// using default claim type from the frameworkidentity.AddClaim(new Claim(ClaimTypes.Email, applicationUser.Email));authenticationManager.SignIn(new AuthenticationProperties()
{ IsPersistent = isPersistent }, identity); }


你可以在这里为所有user添加默认的claims,但有一个IClaimsIdentityFactory类(赋给UserManager),只有一个方法:

public interface IClaimsIdentityFactory<TUser, TKey> where TUser : 
           class, IUser<TKey> where TKey : IEquatable<TKey> {
    /// <summary>/// Create a ClaimsIdentity from an user using a UserManager  
 
/// </summary>Task<ClaimsIdentity> CreateAsync(UserManager<TUser, TKey> manager,
TUser user, string authenticationType); }

 AspNet Identity的默认实现是:创建ClaimsIdentity,添加如上所述的默认claims,为user在数据库中存储IdentityUserClaims类型的claims.你可以重写这个实现,并插入你自己的逻辑/claims:

public class MyClaimsIdentityFactory : ClaimsIdentityFactory<ApplicationUser, string>
{  
public override async Task<ClaimsIdentity> CreateAsync(UserManager<ApplicationUser, string>
userManager, ApplicationUser user, string authenticationType){
var claimsIdentity = await base.CreateAsync(userManager, user, authenticationType);claimsIdentity.AddClaim(new Claim("MyApplication:GroupId", "42"));
return claimsIdentity;} }

然后在赋给UserManger:

public UserManager(MyDbContext dbContext): base(new UserStore<ApplicationUser>(dbContext))
{    // other configurations    

// Alternatively you can have DI container to provide this class for better
application flexebility
this.ClaimsIdentityFactory = new MyClaimsIdentityFactory();
}

原文地址:http://www.cnblogs.com/kid1412/p/6403518.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/326866.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

快速排序+时间测试(yyds)

package com.atguigu.sort;import com.sun.org.apache.xpath.internal.WhitespaceStrippingElementMatcher;import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date;/*** 创建人 wdl* 创建时间 2021/3/22* 描述*/ public class QuickSort {public…

bs架构 erp 进销存_从应用架构看生鲜电商信息化建设

编辑导读&#xff1a;对于生鲜电商来说&#xff0c;信息化建设是很重要的一环&#xff0c;所有的业务开展都离不开信息化的支持。本文作者讲从应用架构角度出发&#xff0c;对生鲜电商信息化建设展开分析&#xff0c;希望对你有帮助。一、背景语言共识之前介绍了从业务架构看生…

分布式 | Dubbo 架构设计详解

转载自 分布式 | Dubbo 架构设计详解 Dubbo是Alibaba开源的分布式服务框架&#xff0c;它最大的特点是按照分层的方式来架构&#xff0c;使用这种方式可以使各个层之间解耦合&#xff08;或者最大限度地松耦合&#xff09;。从服务模型的角度来看&#xff0c;Dubbo采用的是一…

完成OSS.Http底层HttpClient重构封装 支持标准库

OSS.Http项目对于.Net Standard标准库的支持已经迁移完毕&#xff0c;OSS开源系列两个最底层的类库已经具备跨运行时支持的能力。由于OSS.Http类库是几年前我参照RestSharp的思路&#xff0c;完成的一个轻量型Http请求框架。由于时间较久底层使用的还是HttpWebRequest&#xff…

归并排序+思路分析

思路分析 代码实现 package com.atguigu.sort;import java.util.Arrays;/*** 创建人 wdl* 创建时间 2021/3/22* 描述*/ public class MergeSort {public static void main(String[] args) {int arr[]{8,4,5,7,1,3,6,2};int temp[]new int[arr.length];mergeSort(arr,0,arr.len…

常数除以0的极限是什么_【极限】第四节 极限运算法则

定理 例题 极限运算法则就像加减乘除四则运算一样&#xff0c;是一种计算规则&#xff0c;那么极限也有属于它自己的一套计算规则。 极限运算法则的常用定理 定理1 两个无穷小的和是无穷小 有限个无穷小之和也是无穷小 定理2 有界函数与无穷小的乘积是无穷小 常数与无穷小的乘积…

Visual Studio 2017将于3月7日发布

继最近一连串候选发布版本之后&#xff0c;微软已经开始针对正式发布Visual Studio 2017做最后准备工作。微软已经宣布2017年3月7日会是VS2017官方发布时间。第一款VS软件问世于1997年&#xff0c;本次发布标志着产品20周年&#xff0c;这些年里包括了Visual J、Visual FoxPro、…

SQL Server 急救包(First Responder Kit)入门教程

如果你的SQL Server数据库运行起来十分缓慢甚至逐渐停止了&#xff0c;恰巧又赶上了你的数据库管理员在休假&#xff0c;你又不知道该如何是好&#xff0c;那么这篇文章会帮助你从学习使用SQL Server急救包&#xff08;SQL Server First Responder Kit&#xff09;开始解决问题…

IE8浏览器缓存问题导致Ajax的GET请求只能执行一次的解决办法

转载自 IE8浏览器缓存问题导致Ajax的GET请求只能执行一次的解决办法 最近在测试兼容性问题的时候发现&#xff0c;使用Ajax的GET请求向后台获取响应结果时&#xff0c;如果是IE8浏览器&#xff0c;第一次发送请求时会得到正常的返回结果&#xff0c;然后当再去发送相同请求访…

基数排序+推导过程

图解 代码实现 package com.atguigu.sort;import java.util.Arrays;/*** 创建人 wdl* 创建时间 2021/3/22* 描述*/ public class RadixSort {public static void main(String[] args) {//53, 3, 542, 748, 14, 214int arr[] {53, 3, 542, 748, 14, 214};radixSort(arr);}//基…

Xamarin的坑 - 绑定(一) - 拿微信iOS SDK 简单说起

编者语&#xff1a;Xamarin 并入微软快一年了&#xff0c;在国内推广还是慢&#xff0c;主要有两个方面&#xff0c;Xamarin在国内的本地化不足真正在国内的解决方案基本上没有&#xff0c;第二就是和本土的一些主要SDK接入案例基本上也没有。上述原因令不少企业放弃使用这个很…

二分查找+思路分析

思路分析 代码实现 package com.atguigu.search;/*** 创建人 wdl* 创建时间 2021/3/23* 描述*/ //注意&#xff1a;使用二分查找的前提是&#xff0c;该数组是有序的 public class BinarySearch {public static void main(String[] args) {int arr[]{1,8,10,89,1000,1234};int…

SQLServer On Linux Package List on CentOS

问题引出 “鸟儿啊&#xff0c;到底SQLServer on Linux肚里装了多少东西&#xff0c;在我们的CentOS系统安装了哪些物理文件呢&#xff1f;”&#xff0c;老鸟这天火急火燎的问道。“这个啊&#xff1f;让本鸟帮你一探究竟。”&#xff0c;菜鸟耐心回答道。 问题分析 菜鸟一边想…

开发环境 Minio 添加桶的操作流程-页面操作

命令操作 d开发环境 Minio 添加桶的操作流程_摇曳的精灵的博客-CSDN博客_minio创建桶 页面操作

冬至快乐

男生关注会更帅&#xff0c;女生关注会更美&#xff01;冬至冬至到&#xff0c;吃水饺&#xff0c;颗颗都有年味道。头常挠&#xff0c;口常笑&#xff0c;睿智快乐常围绕。摇摇头&#xff0c;晃晃脑&#xff0c;轻松健康直到腰。扭扭臂&#xff0c;捏捏脚&#xff0c;健康到底…

介绍Portable PDB

为了调试编译的应用程序&#xff0c;有必要将IL代码或二进制的机器代码与源代码行进行匹配。虽然数据可以嵌入在应用程序中&#xff0c;但这会显著增加EXE或DLL文件的大小。取而代之的是&#xff0c;通常会使用单独的“symbols”文件。在Windows平台上&#xff0c;这被称为PDB或…

RedisGeo实现增删改查 java计算指定坐标最近的距离并排序

利用Redis的Geo功能实现查找附近的位 - 云社区 - 腾讯云 package com.easy.hotel.pms.util;import com.easy.hotel.common.data.tenant.TenantContextHolder; import com.easy.hotel.pms.mapper.CommunityMapper; import com.easy.hotel.pms.service.impl.CommunityServiceImpl…

没有注册类 (异常来自 HRESULT:0x80040154 (REGDB_E_CLASSNOTREG))

今天在开发指纹识别的项目时候&#xff0c;出现了个问题&#xff0c;这个问题之前也没有见过&#xff0c;所以无从下手&#xff0c;只能从网上找解决方法&#xff0c;找了半天说要注册com组件啥的&#xff0c;我老是注册不成功&#xff0c;后来瞎捣鼓终于解决了&#xff0c;原因…

插值查找+代码实现+注意事项

图解 代码实现 package com.atguigu.search;import java.util.Arrays;/*** 创建人 wdl* 创建时间 2021/3/23* 描述*/ public class InsertValueSearch {public static void main(String[] args) {int[] arrnew int[100];for (int i 0; i < 100; i) {arr[i]i1;}// S…