在ASP.NET Core 中,仍然沿用了ASP.NET裡面的Identity 元件庫,負責對用戶的身份進行認證,總體來說的話,沒有MVC 5 裡面那麼複雜,因為在MVC 5裡面引入了OWIN的東西,所以很多初學者在學習來很費勁,對於Identity 都是一頭霧水,包括我也是,曾經在學identity 這個東西前後花了一個多月來搞懂裡面的原理。所以大部分開發者對於 Identity 並沒有愛,也沒有使用它,會覺得被綁架。
值得慶幸的是,在ASP.NET Core 中,由於對模組的抽象化逐漸清晰,以及中間件的使用,這使得Identity 的學習和使用路線變得更加平易近人,下面就讓我們一起來看看吧。
在開始之前,讓我們先忘記它和Entity Framework
的關係,也忘記它和Authentication
的關係,我們先學習幾個英文單字。
有這麼多「單字」你可能需要弄清楚:
# 1: Claims
##大家應該都知道身分證長什麼樣子的,如下: 其中,姓名:歐巴馬;性別:男;民族:肯亞;出生:1961.08.04,等等這些身分訊息,可以看出都是一個一個的鍵值對,那如果我們想在程式中存這些東西,怎麼樣來設計呢?對,你可能想到了使用一個字典進行存儲,一個Key,一個Value剛好滿足需求。但是Key,Value的話感覺不太友好,不太物件導向,所以如果我們做成一個物件的話,是不是更好一些呢?最起碼你可以用vs的智慧提示了吧,我們修改一下,改成下面這樣:
//我给对象取一个名字叫`Claim`你没有意见吧 public class Claim { public string ClaimType { get; set; } public string ClaimValue { get; set; } }
一個鍵值對。這時候姓名:歐巴馬是不是可以存進去了。
ClaimType呢?很多常用的都在裡面呢,一起看看吧:
這裡延伸第一個知識點:ClaimTypes
##為了閱讀體驗,截圖我只放了一部分喔。可以看到有什麼Name,
Email,Gender,MobilePhone等常用的都已經有了,其他的還有很多。細心的讀者可能注意了,它的命名空間是System.Security.Claims,那就說明這個東西是.net 框架
的一部分,嗯,我們暫時只需要知道這麼多就OK了。 Claim
完畢,是不是很簡單,其他地方怎麼翻譯我不管,在本篇文章裡面,它叫 “證件單元”。
# 2: ClaimsIdentity在有了「
證件單元」之後,我們就用它可以製造一張身分證了,那麼應該怎麼樣製造呢?有些同學可能已經想到了,對,就是新建一個對象,然後在建構函數裡面把身分證單元傳輸進去,然後就得到一張身分證了。我們給這張身分證取一個英文名字叫“ClaimsIdentity”,這個名字看起來還蠻符合的,既有Claims 表示其組成部分,又有表示其用途的Identity(身分),很滿意的一個名字。 實際上,在現實生活中,我們的身分證有一部分資訊是隱藏的,有一部分是可以直接看到的。例如新一代的身分證裡面儲存了你的指紋資訊你是看不到的,這些都儲存在身分證裡面的晶片中,那能看到的例如姓名啊,年齡啊等。我們在設計一個物件的時候也是一樣,需要露出一些東西,那這裡我們的 ClaimsIdentity 就暴露出來一個 Name,Lable等。
我们造的身份证(ClaimsIdentity)还有一个重要的属性就是类型(AuthenticationType),等等,AuthenticationType是什么东西?看起来有点眼熟的样子。我们知道我们自己的身份证是干嘛的吧,就是用来证明我们的身份的,在你证明身份出示它的时候,其实它有很多种形式载体的,什么意思呢?比如你可以直接拿出实体形式的身份证,那也可以是纸张形式的复印件,也可以是电子形式的电子码等等,这个时候就需要有一个能够表示其存在形式的类型字段,对,这个AuthenticationType就是干这个事情的。
然后我们在给我们的身份证添加一些润色,让其看起来好看,比如提供一些方法添加 Claims 的,删除 Claims的,写到二进制流里面的啊等等,最终我们的身份证对象看起来基本上是这样了:
public class ClaimsIdentity { public ClaimsIdentity(IEnumerable<Claim> claims){} //名字这么重要,当然不能让别人随便改啊,所以我不许 set,除了我儿子跟我姓,所以是 virtual 的 public virtual string Name { get; } public string Label { get; set; } //这是我的证件类型,也很重要,同样不许 set public virtual string AuthenticationType { get; } public virtual void AddClaim(Claim claim); public virtual void RemoveClaim(Claim claim); public virtual void FindClaim(Claim claim); }
嗯,到这里,我们的身份证看起来似乎很完美了,但是从面向对象的角度来说好像还少了点什么东西? 对~,还是抽象,我们需要抽象出来一个接口来进行一些约束,约束什么呢?既然作为一个证件,那么肯定会涉及到这几个属性信息:
1、名字。2、类型。3、证件是否合法。
反应到接口里面的话就是如下,我们给接口取个名字叫:“身份(IIdentity)”:
这里延伸第二个知识点:IIdentity接口。
// 定义证件对象的基本功能。 public interface IIdentity { //证件名称 string Name { get; } // 用于标识证件的载体类型。 string AuthenticationType { get; } //是否是合法的证件。 bool IsAuthenticated { get; } }
所以我们的 ClaimsIdentity 最终看起来定义就是这样的了:
public class ClaimsIdentity : IIdentity { //...... }
ClaimsIdentity 介绍完毕,是不是发现也很简单,其他地方怎么翻译我不管,在本篇文章里面,它叫 “身份证”。
# 3: ClaimsPrincipal
有了身份证,我们就能证明我就是我了,有些时候一个人有很多张身份证,你猜这个人是干嘛的? 对,不是黄牛就是诈骗犯。
但是,有些时候一个人还有其他很多种身份,你猜这个人是干嘛的?这就很正常了对不对,比如你可以同时是一名教师,母亲,商人。如果你想证明你同时有这几种身份的时候,你可能需要出示教师证,你孩子的出生证,法人代表的营业执照证。
在程序中,一个身份证不仅仅代表你这个人了,而是代表一个身份,是证明你自己的主要身份哦。如果一个人还有其他很多种身份,这个时候就需要有一个东西(载体)来携带着这些证件了对吧?OK,我们给需要携带证件的这个对象取一个贴切点的名字,叫“证件当事人(ClaimsPrincipal)”吧。
以下是 Principal 这个单词在词典给出的解释,我用它你应该没意见吧:
principal ['prɪnsəpl] adj. 主要的;资本的 n. 首长;校长;资本;当事人登入後複製
这个时候可能有同学会问了,是不是应该叫ClaimsIdentityPrincipal
比较好呢?嗯,我也觉得应该叫 ClaimsIdentityPrincipal 可能更好一点,或许微软的人偷懒了,简写成了ClaimsPrincipal
。
知道其功能后,代码就很好写了,和上面ClaimsIdentity一样的套路:
public class ClaimsPrincipal { //把拥有的证件都给当事人 public ClaimsPrincipal(IEnumerable<ClaimsIdentity> identities){} //当事人的主身份呢 public virtual IIdentity Identity { get; } public virtual IEnumerable<ClaimsIdentity> Identities { get; } public virtual void AddIdentity(ClaimsIdentity identity); //为什么没有RemoveIdentity , 留给大家思考吧? }
当时人看起来也几乎完美了,但是我们还需要对其抽象一下,抽象哪些东西呢? 作为一个当事人,你应该有一个主身份吧,就是你的身份证咯,可能你还会用到角色(角色后面会详细介绍,这里你知道有这么个东西就行了)。
这里延伸第三个知识点:IPrincipal 接口。
public interface IPrincipal { //身份 IIdentity Identity { get; } //在否属于某个角色 bool IsInRole(string role); }
然后,我们的 证件当事人 看起来应该是这样的:
public class ClaimsPrincipal : IPrincipal { //... }
ClaimsPrincipal 介绍完了,也很简单吧? 其他地方怎么翻译我不管,在本篇文章里面,它叫 “证件当事人”。
想在,我们已经知道了 “证件单元(Claims)” , “身份证(ClaimsIdentity)” , “证件当事人(ClaimsPrincipal)”,并且整理清楚了他们之间的逻辑关系,趁热打铁,下面这个图是一个identity登入部分的不完全示意图,虚线圈出来的部分应该可以看懂了吧:
可以看出,首先我们在app这边有一些证件单元,然后调用ClaimsIdentity
把证件单元初始化为一个身份证,然后再把身份证交给证件当事人由其保管。
才把 Getting Started 写完,发现已经这么长了,所以打算写成一个系列了,可能3 - 4篇吧。
好了,本篇就先介紹到這裡,在本篇部落格中,我們學會了幾個英文單詞,並且知道了這些英文單字在程序中是扮演這怎麼樣一個物件。並且根據圖我們知道了這些物件在整個認證系統種處在怎麼樣一個位置。 我發現如果想把identity 講清楚僅靠這篇博客是不夠的,下一篇我們將對.NET Authentication
中間件進行抽絲剝繭,直到掌握.NET的整個認證系統後,我們再來來看看Identiy 到底和Entity Framework 有著怎樣的愛恨情仇。
這只是一個開始,大家如果覺得這篇部落格對您有幫助的話,感謝您的【推薦】,如果你對.NET Core 感興趣可以關注我,我會定期在博客分享關於.NET Core 的學習心得。
以上是ASP.NET Core 之 Identity入門的詳細內容。更多資訊請關注PHP中文網其他相關文章!