哈喽你们又见面啦,感受很久没更新了,这几天看了一本书《解忧杂货铺》,嗯挺好的,推荐一下😀。html
不过仍是要学习了,这些天简单的看了看 Id4 的资料,才发现原来关于 Id4 的系列文章真是数不胜数,并且还有不少的深度好文章, 说的灰常之详细,因此一度打消了我写这一系列的冲动和信心,不过仍是有一部分的小伙伴尚未学习过,因此我决定我之后就把 IdentityServer4 的基础概念知识点,就少写些,重点写如何在项目中使用吧,本文的知识点,简单过一遍,脑子里有这个东西就好了,再之后的开发中,多动手就知道了,特别简单的,这里说明一下,在之前的Blog.Core 系列中,有关 JWT 的知识,我单拎出来一个小Demo,有不懂的能够下载看看(https://github.com/anjoy8/Blog.Core/blob/master/Blog.Core/wwwroot/Autho.jwt.rar)。vue
IdentityServer 是基于OpenID Connect协议标准的身份认证和受权程序,它实现了OpenID Connect 和 OAuth 2.0 协议。node
一样的角色,不一样的文档使用不一样的术语。在有些文档中,它(IdentityServer)可能会被叫作安全令牌服务器(security token service)、身份提供者(identity provider)、受权服务器(authorization server)、 标识提供方((IP-STS,什么是IP-STS)等等。git
可是它们都是同样的,都是向客户端发送安全令牌(security token),github
IdentityServer有许多功能:web
用户是使用已注册的客户端(指在id4中已经注册)访问资源的人。算法
客户端就是从identityserver请求令牌的软件(你能够理解为一个app便可),既能够经过身份认证令牌来验证识别用户身份,又能够经过受权令牌来访问服务端的资源。可是客户端首先必须在申请令牌前已经在identityserver服务中注册过。chrome
实际客户端不只能够是Web应用程序,app或桌面应用程序(你就理解为pc端的软件便可),SPA,服务器进程等。数据库
资源就是你想用identityserver保护的东东,能够是用户的身份数据或者api资源。
每个资源都有一个惟一的名称,客户端使用这个惟一的名称来肯定想访问哪个资源(在访问以前,实际identityserver服务端已经配置好了哪一个客户端能够访问哪一个资源,因此你没必要理解为客户端只要指定名称他们就能够随便访问任何一个资源)。json
用户的身份信息实际由一组claim组成,例如姓名或者邮件都会包含在身份信息中(未来经过identityserver校验后都会返回给被调用的客户端)。
API资源就是客户端想要调用的功能(一般以json或xml的格式返回给客户端,例如webapi,wcf,webservice),一般经过webapi来创建模型,可是不必定是webapi,我刚才已经强调可使其余类型的格式,这个要看具体的使用场景了。
身份令牌表示身份验证过程的结果。 它最低限度地标识了某个用户,还包含了用户的认证时间和认证方式。 它能够包含额外身份数据。
一个身份令牌指的就是对认证过程的描述。它至少要标识某个用户(Called the sub aka subject claim)的主身份信息,和该用户的认证时间和认证方式。可是身份令牌能够包含额外的身份数据,具体开发者能够自行设定,可是通常状况为了确保数据传输的效率,开发者通常不作过多额外的设置,你们也能够根据使用场景自行决定。
访问令牌容许访问API资源。 客户端请求访问令牌并将其转发到API。 访问令牌包含有关客户端和用户的信息(若是存在)。 API使用该信息来受权访问其数据。
访问令牌容许客户端访问某个 API 资源。客户端请求到访问令牌,而后使用这个令牌来访问 API资源。访问令牌包含了客户端和用户(若是有的话,这取决于业务是否须要,但一般没必要要)的相关信息,API经过这些令牌信息来授予客户端的数据访问权限。
access token 是客户端访问资源服务器的令牌。拥有这个令牌表明着获得用户的受权。然而,这个受权应该是临时的,有必定有效期。这是由于,access token 在使用的过程当中可能会泄露。给 access token 限定一个较短的有效期能够下降因 access token 泄露而带来的风险。
然而引入了有效期以后,客户端使用起来就不那么方便了。每当 access token 过时,客户端就必须从新向用户索要受权。这样用户可能每隔几天,甚至天天都须要进行受权操做。这是一件很是影响用户体验的事情。但愿有一种方法,能够避免这种状况。
因而 Oauth2.0 引入了 refresh token 机制。refresh token 的做用是用来刷新 access token。鉴权服务器提供一个刷新接口,例如:
http://xxx.xxx.com/refresh?refreshtoken=&client_id=
传入 refresh token 和 client_id,鉴权服务器验证经过后,返回一个新的 access token。为了安全,Oauth2.0 引入了两个措施:
1,Oauth2.0 要求,refresh token 必定是保存在客户端的服务器上的,而毫不能存放在狭义的客户端(例如移动 app、PC端软件) 上。调用 refresh 接口的时候,必定是从服务器到服务器的访问;
2,Oauth2.0 引入了 client_secret 机制。即每个 client_id 都对应一个 client_secret。这个 client_secret 会在客户端申请 client_id 时,随 client_id 一块儿分配给客户端。客户端必须把 client_secret 妥善保管在服务器上,决不能泄露。刷新 access token 时,须要验证这个 client_secret。
因而,实际上的刷新接口应该是相似这样的:
http://xxx.xxx.com/refresh?refreshtoken=&client_id=&client_secret=
以上就是 refresh token 机制。refresh token 的有效期很是长,会在用户受权时,随 access token 一块儿重定向到回调 url,传递给客户端。
OAuth(开放受权)是一个开放标准,容许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。就好比我用QQ登陆博客园,那博客园(第三方应用)的昵称就能够是个人QQ(某网站)昵称,它获取到了个人QQ昵称,并存到了博客园的数据库,我之后就一直可使用QQ来登陆博客园,可是博客园殊不知道我QQ的用户名和密码。
OAuth 容许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每个令牌受权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的 2 小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth 让用户能够受权第三方网站访问他们存储在另外服务提供者的某些特定信息,而非全部内容。
OAuth 2.0 四种受权模式:
受权码模式(authorization code)
简化模式(implicit grant type)
密码模式(resource owner password credentials)
客户端模式(Client Credentials Grant)
具体的概念和如何使用不细说,之后会分四篇文章详细说明,今天主要是基础知识和项目的搭建。
简单来讲:
为何开发者要使用OpenID Connect?
由于它很简单,可靠,安全,并让他们摆脱困难和危险的存储和管理别人的密码。也有好处,它让用户的生活更容易在网站注册和注册从而减小遗弃。
要比较JWT和OAuth2,首先要明白一点就是,这两个根本没有可比性,是两个彻底不一样的东西。
JWT是一种认证协议
JWT提供了一种用于发布接入令牌(Access Token),并对发布的签名接入令牌进行验证的方法。 令牌(Token)自己包含了一系列声明,应用程序能够根据这些声明限制用户对资源的访问。
OAuth2是一种受权框架
另外一方面,OAuth2是一种受权框架,提供了一套详细的受权机制(指导)。用户或应用能够经过公开的或私有的设置,受权第三方应用访问特定资源。
既然 JWT和OAuth2.0 没有可比性,为何还要把这两个放在一块儿说呢?实际中确实会有不少人拿 JWT和OAuth2.0 做比较。不少状况下,在讨论OAuth2的实现时,会把JSON Web Token做为一种认证机制使用。这也是为何他们会常常一块儿出现。
一个网站若是想要接入 OpenID 认证是很是简单的,不须要建立应用,不须要 App Key ,不须要 Secret ,只须要将用户导向 OpenID Provider 的 Entry 并带上 Callback ,用户只要赞成提供信息,你就能够拿到这个用户的“惟一标识”。
请注意这里我使用了“惟一标识”这种说法,由于对于网站来讲,OpenID Provider 提供的既不是用户的 UID ,也不是用户的 E-Mail ,好比 Google 在默认状况下提供的就是一个几十位长的字符串,这个字符串是随机生成的,第三方网站没法从中得到用户的任何私人信息。这么说可能很抽象,举个例子:
好比我用 Google 的 OpenID 服务登陆 xxx.com , xxx.com 先把我导向 Google 的受权页面,我使用 Google 账号 test@gmail.com 登陆并赞成后,页面跳回 xxx.com , xxx.com 拿到了个人“惟一标识”,这个惟一标识多是 cdxxxxxxxaaf6b73bcb04a1 ,xxx.com 从这个字符串里没法得到任何 test@gmail.com 的我的信息(甚至连邮箱地址也不知道), xxx.com 只知道之后只要使用谷歌登陆并返回 cdxxxxxxxaaf6b73bcb04a1 这个标识符,那就是我在登陆。
显而易见,OpenID 是专为登陆认证而生,它使用简单,门槛很低,可是若是你想在认证过程当中得到用户的其余信息(好比 E-Mail )就得多作一步了。
你这个时候可能就会问了,那有哪些网站使用的是 OpenID 登陆的呢,我简单看了看,好像都是基于 OAuth 开发的,并且也看到了一个博问,是这么说的:
具体的我们就不分析了,如今基本都是使用的 OAuth2.0 ,不过如今使用 Id4 是结合了 OAuth2.0 和 OpenID的。
与 OpenID 相比,网站想接入 OAuth 要稍微麻烦点,网站须要先建立应用,拿到 Key 和 Secret ,才能接入 Provider 。
OAuth 的受权过程并非身份认证的过程,这一点须要特别清楚,网站走完 OAuth 流程并拿到用户的受权 token 后还须要经过 token 调用相应的用户信息接口才能得到“惟一标识”,举个例子:
我想经过新浪微博登陆 xxx.com ,xxx.com 要先把我 redirect 到新浪微博的受权页面,我经过微博账号登陆并受权后,页面跳回 xxx.com ,xxx.com 拿到个人访问 token 后还要再调用一个接口来得到个人新浪会员 UID ,这个 UID 就是新浪用户的“惟一标识”了。
能够看出,OAuth 相对于 OpenID 最大的区别就是,网站其实是拿到了你的账户访问权限继而确认你的身份,这是一个安全隐患,由于网站在拿到你的“惟一标识”的同时还拿到了一把你的帐户的 “临时钥匙”。至于网站会不会拿这把钥匙“干坏事”,这个只有站长内心清楚。同时 OAuth 还比 OpenID 多了几个额外的请求步骤,登陆所费时间必定是长于 OpenID 的。
OAuth关注的是authorization;而OpenID侧重的是authentication。从表面上看,这两个英文单词很容易混淆,但实际上,它们的含义有本质的区别:
OAuth关注的是受权,即:“用户能作什么”;而OpenID关注的是证实,即:“用户是谁”。
OpenID是关于证实、证明身份(Authentication)的,比如火车站进站的时候拿出身份证和车票来看,比对是否同一我的。这是在回答「我是谁?这就是我」,是为了证明「这不是一个匿名的不可查的信息源头」,由于匿名对象和信息对网络服务商来讲很差统计管理,也不利于产生价值。
OAuth 是关于受权、许可(Authorization)的,比如坐飞机过安检的时候除了看身份证,还要求掏出兜里的东西,拿出包里的东西、手机等随身物品以便检查,这时就须要获得被检查人的许可才行,被检查人有权利扭头就走,但要想登机,必须给予许可、掏出物品。这是在回答「我赞成让你对我进一步作些什么」,是为了在被授予权限的前提下,更多的获取除了帐号密码之外的我的信息,例如:联系人通信录,邮箱号,电话号,地址,照片,聊天记录,网络发言、活动记录,GPS 信息等等,来知足用户对服务的功能须要,或者「其余须要」。
//这里有个网友的说明,我感受挺好的
现在愈来愈多的网站,以及一些应用程序都开始使用第三方社交平台帐户登陆,那这里就会涉及到安全性的问题,隐私的问题,你不能随意来获取个人资料,固然你来使用个人资料,你要通过用户的赞成,那这个用户是否是我平台上,仍是要来向我求证,那在这个过程当中,实际上就出现了两个过程,咱们仍是直接使用上次的例子来讲明,比较直观,CSDN使用QQ登陆,进入csdn的登陆页,点击使用QQ登陆:
在进入到QQ登陆界面后,最开始是要请求认证,用户输入QQ号和密码,点击登陆,腾讯互联会先进行验证该用户是否为个人用户,若是是个人用户,那么我会通知你(CSDN),他是个人用户,你可使用该帐户登陆你的系统,这个过程就是认证(Authentication),认证就是证实你是谁,你是不是真实存在的,就好像,快递员来给你送快递,让你出示你的身份证,他肯定你是本人后,把快递给你,这就是OpenID。
而在QQ受权登陆下方,有两给CheckBox复选框,能够容许CSDN得到您的昵称、头像、性别,这是在认证以后的事了,在腾讯互联你是我平台的用户后,你能够本身选择CSDN是否有权去获取你的相关信息,当你勾选后,腾讯互联就把你的这些基本信息给了CSDN,这个过程就是受权(Authorization),受权就是肯定了你是谁后,又把属于你的东西给了别人,犹如你向快递员出示了身份证,而后你又把你房门的密码给了他,并告诉他说,我把房门密码给你,你帮我放到我客厅里吧。
简要而言,OIDC是一种安全机制,用于应用链接到身份认证服务器(Identity Service)获取用户信息,并将这些信息以安全可靠的方法返回给应用。
在最初,由于OpenID1/2常常和OAuth协议(一种受权协议)一块儿说起,因此两者常常被搞混。
(身份验证)+ OAuth 2.0 = OpenID Connect
OpenID Connect是“认证”和“受权”的结合,由于其基于OAuth协议,因此OpenID-Connect协议中也包含了client_id、client_secret还有redirect_uri等字段标识。这些信息被保存在“身份认证服务器”,以确保特定的客户端收到的信息只来自于合法的应用平台。这样作是目的是为了防止client_id泄露而形成的恶意网站发起的OIDC流程。
举个例子。某个用户使用Facebook应用“What online quiz best describes you?” ,该应用能够经过Facebook帐号登陆,则你能够在应用中发起请求到“身份认证服务器”(也就是Facebook的服务器)请求登陆。这时你会看到以下界面,询问是否受权。
你能够参考官方文档:Docs » Welcome to IdentityServer4
这个过程很简单,由于你能看这个系列,证实你的 NetCore 功底已经很高了,至少中等,若是不会,请时光机回到个人第一个先后端分离系列。
一、建立一个新的ASP.NET Core项目;//可使用命令行建立
二、选择“空白”选项;//这里建立空的应用程序是为了后面方便引入UI界面
三、设置项目使用 kestrel 服务器,删除IIS;
四、配置端口号;//我这里是5002,可自定义设置
一、使用 nuget 添加 IdentityServer4 包;//固然你也可使用命令: Install-Package IdentityServer4
二、配置认证服务中间件管道;//app.UseIdentityServer();
三、配置 IdentityServer 相关服务;
这里不只要把 IdentityServer 注册到容器中, 还要至少对其配置四点内容:
一、这个 Authorization Server 保护了哪些 API (资源);
二、哪些客户端 Client(应用) 可使用这个 Authorization Server;
三、指定可使用 Authorization Server 受权的 Users(用户);
四、指定做用域定义系统中的 IdentityResources 资源;//这个在之后说到 OpenId的时候再说,这里伏笔
首先在项目根目录下,创建文件 InMemoryConfig.cs:
public static class InMemoryConfig { // 这个 Authorization Server 保护了哪些 API (资源) public static IEnumerable<ApiResource> GetApiResources() { return new[] { new ApiResource("blog.core.api", "Blog.Core API") }; } // 哪些客户端 Client(应用) 可使用这个 Authorization Server public static IEnumerable<Client> GetClients() { return new[] { new Client { ClientId = "blogvuejs",//定义客户端 Id ClientSecrets = new [] { new Secret("secret".Sha256()) },//Client用来获取token AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,//这里使用的是经过用户名密码和ClientCredentials来换取token的方式. ClientCredentials容许Client只使用ClientSecrets来获取token. 这比较适合那种没有用户参与的api动做 AllowedScopes = new [] { "blog.core.api" }// 容许访问的 API 资源 } }; } // 指定可使用 Authorization Server 受权的 Users(用户) public static IEnumerable<TestUser> Users() { return new[] { new TestUser { SubjectId = "1", Username = "laozhang", Password = "laozhang" } }; } }
GetApiResources:这里指定了name和display name, 之后api使用authorization server的时候, 这个name必定要一致, 不然就很差用的。
GetClients: Client的属性太多了,基本的上边已经注释了
Users: 这里的内存用户的类型是TestUser, 只适合学习和测试使用, 实际生产环境中仍是须要使用数据库来存储用户信息的, 例如接下来会使用asp.net core identity. TestUser的SubjectId是惟一标识.
而后回到 Startup 的 ConfigureServices 方法种:
咱们须要对token进行签名, 这意味着 identity server 须要一对public和private key。不过咱们如今是本地调试,能够告诉identity server在程序的运行时候对这项工做进行设定: AddDeveloperSigningCredential(),它默认会存到硬盘上的, 因此每次重启服务不会破坏开发时的数据同步。这个方法只适合用于identity server4在单个机器运行, 若是是 production 你得使用AddSigningCredential()这个方法:
public class Startup { public IConfiguration Configuration { get; } public IHostingEnvironment Environment { get; } public Startup(IConfiguration configuration, IHostingEnvironment environment) { Configuration = configuration; Environment = environment; } public void ConfigureServices(IServiceCollection services) { services.AddMvc(); var builder = services.AddIdentityServer(options => { options.Events.RaiseErrorEvents = true; options.Events.RaiseInformationEvents = true; options.Events.RaiseFailureEvents = true; options.Events.RaiseSuccessEvents = true; }) // in-memory, code config .AddTestUsers(InMemoryConfig.Users().ToList()) .AddInMemoryApiResources(InMemoryConfig.GetApiResources()) .AddInMemoryClients(InMemoryConfig.GetClients()); builder.AddDeveloperSigningCredential(); if (Environment.IsDevelopment()) { builder.AddDeveloperSigningCredential(); } else { throw new Exception("need to configure key material"); } services.AddAuthentication();//配置认证服务 } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseIdentityServer();//启动 IdentityServer app.UseMvcWithDefaultRoute();//启动 MVC } }
而后运行一下,在 Postman 中,尝试经过上边的用户名密码来获取 Token :
是否是很熟悉,若是你用过 NetCore 的受权验证的话,这些确定都能看懂。
这里你必定很好奇,我是怎么知道要使用这个地址 localhost:5002/connect/token 来获取Token的? ,一共还有多少个接口地址呢,要是有一个界面就行了。别着急往下看。IdentityServer4 官方已经考虑到了。
官方为咱们提供了一个快速启动的UI界面,咱们只须要下载下来便可,这里有两个方法:
一、直接从这个地址下来下载,拷贝到项目中,一共三个文件夹;// https://github.com/IdentityServer/IdentityServer4.Quickstart.UI
二、在当前文件夹中执行命令,自动下载;
iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/IdentityServer/IdentityServer4.Quickstart.UI/master/getmaster.ps1'))
这样咱们的项目界面已经成功的获取到了,除此以外,记得要配置中间件来使用静态文件:
app.UseStaticFiles();
配置好后,F5运行,就能够看到了界面,并且也看到了咱们上边说到的 token 获取的接口地址 localhost:5002/connect/token:
(可能这个 Json 格式和你的不同,由于我安装了chrome 的扩展插件了——JSONView)
由于篇幅的问题,这个下次再详细说明,不过个人 GitHub 上已经写好了,有须要的能够看看。
这里信息暂时没有用处,只是先做为一个备注记录,待之后补充完善:
参考地址:https://www.cnblogs.com/guolianyu/p/9872661.html
一、HS256与RS256的区别
HS256 使用密钥生成对称的签名,RS256 使用成非对称进行签名。简单地说,HS256 必须与任何想要验证 JWT的 客户端或 API 共享秘密。
RS256 生成非对称签名,这意味着必须使用私钥来签签名 JWT,而且必须使用对应的公钥来验证签名。与对称算法不一样,使用 RS256 能够保证服务端是 JWT 的签名者,由于服务端是惟一拥有私钥的一方。这样作将再也不须要在许多应用程序之间共享私钥
二、建立自签名证书(操做步骤)
生产环境(负载集群)通常须要使用固定的证书签名与验签,以确保重启服务端或负载的时候 Token 都能验签经过。(不使用临时证书)
那么证书如何生成请看下面分解步骤:
第一种:使用OpenSSL生成证书,注:RSA加密证书长度要2048以上,不然服务运行会抛异常
#Linux系统生成证书:(推荐使用) sudo yum install openssl (CentOS)
#生成私钥文件 openssl genrsa -out idsrv4.key 2048
#建立证书签名请求文件 CSR(Certificate Signing Request),用于提交给证书颁发机构(即 Certification Authority (CA))即对证书签名,申请一个数字证书。 openssl req -new -key idsrv4.key -out idsrv4.csr
#生成自签名证书(证书颁发机构(CA)签名后的证书,由于本身作测试那么证书的申请机构和颁发机构都是本身,crt 证书包含持有人的信息,持有人的公钥,以及签署者的签名等信息。当用户安装了证书以后,便意味着信任了这份证书,同时拥有了其中的公钥。) openssl x509 -req -days 365 -in idsrv4.csr -signkey idsrv4.key -out idsrv4.crt (包含公钥)
#自签名证书与私匙合并成一个文件(注:.pfx中能够加密码保护,因此相对安全些) openssl pkcs12 -export -in idsrv4.crt -inkey idsrv4.key -out idsrv4.pfx (注:在生成的过程当中会让咱们输入Export Password)
证书截图以下:
第二种:
openssl req -newkey rsa:2048 -nodes -keyout idsrv4.key -x509 -days 365 -out idsrv4.cer openssl pkcs12 -export -in idsrv4.cer -inkey idsrv4.key -out idsrv4.pfx
生成以下:
三、证书生成以后就可进入VS2017中配置
拷贝生成的证书,放到认证/受权服务器项目中。(VS中配置文件设置文件始终复制),最后把证书路径和密码配置到 IdentityServer 中,由于咱们自签名的证书是 PKCS12 (我的数字证书标准,Public Key Cryptography Standards #12) 标准包含私钥与公钥)标准,包含了公钥和私钥。
A、在appsetting.json 配置文件中添加以下:此处须要配置password,自定义便可。
B、在starup.cs中ConfigureServices方法中配置以下便可。
配置完后便可。咱们启动IDS4项目便可生成加密的token。
今天我们主要经过一个小栗子,把咱们的IdentityServer受权服务器搭建好了,而且作了相应配置,也获取到了 Token ,是否是很简单?感受 Id4 也没有咱们想象的那么难是吧,关键就是上边的Config.cs 中的三个配置,总结来讲:
有哪些用户能够经过哪些客户端来访问咱们的哪些API保护资源。
这要咱们这些配置好了,天然咱们也就可使用 Id4 了,固然这个仅仅是获取到了 Token,那如何连数据库,如何应用在 API 资源服务器,又如何在客户端配置呢,我们下次再见咯。
https://github.com/anjoy8/Blog.IdentityServer
-- END ---