前言
我们现在日常生活中,会使用各式各样的应用程序,层出不穷,其中有基于网页浏览方式的应用,有基于手机端的App,甚至有基于流行的公众号和小程序等等,这些应用,我们不仅要实现各个应用的功能之外,还要考虑各个应用之间的交互作用,其中身份的认证和授权就是每个应用必不可少的的一部分。
所以我们以身份认证和授权这一部分为例,需要考虑各个应用直接的交互,统一管理以及信息安全问题。
而现在的互联网,对于信息安全要求又十分苛刻,所以一套统一的身份认证和授权就至关重要。
所以,我们可以根据Identity Server4
框架开发一套统一的身份认证和授权项目应用在平时的多个项目中,实现多平台应用授权统一管理。
说明
我们通过查看 IdentityServer4官网,就可以看到给出的定义:
IdentityServer4 is an OpenID Connect and OAuth 2.0 framework for ASP.NET Core.
OpenID Connect + OAuth2.0 相结合的认证框架
由此可见,IdentityServer是基于OpenID Connect协议标准的身份认证和授权程序,实现了OpenID Connect和OAuth2.0协议的结合。
所以,IdentityServer4是为ASP.NET CORE量身定制的实现了OpenId Connect和OAuth2.0协议的认证授权中间件。通常,你构建(或重新使用)包含登录和注销页面的应用程序,IdentityServer中间件会向其添加必要的协议头,以便客户端应用程序可以使用这些标准协议与其对话。
2.1 特性
通过不同的文献使用的术语我们会发现,同一个概念可能存在着多种解释,比如有些把他称为安全令牌服务(Security Token Service), 身份提供(Identity Provider),授权服务器(Authorization Server),IP-STS 等等。其实他们都是一个意思,目的都是在软件应用中为客户端颁发令牌并用于安全访问的。
2.2 功能
引申
3.1 OAuth2.0
OAuth2.0 是OAuth协议的延续,OAuth2.0 关注客户端开发者的简易性,为用户资源提供一个安全的、开放而有建议的标准。是目前流行的授权机制,用于授权第三方应用就可以获取该用户资源。因此OAuth是安全的。
为了安全,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。
3.1.1 场景
OAuth2.0 是目前最流行的授权机制,用来授权第三方应用,获取用户数据。
(以下以 第三方A网站用户访问授权获取在B网站资源 为例 。参考:理解OAuth 2.0)
为了让A网站应用访问在B网站上的存储的照片、视频或者联系方式等等私密资源,我们可能需要做到的就是让B网站同意A网站访问读取这些资源,那么,在传统的方式中,会将自己在B网站中的用户名和密码告诉A,后者就可以读取用户的资源信息了,但是这样做存在了严重的问题:
A网站为了后续服务,会保存用户的密码,这样不安全。
B网站必须部署密码登录方式,才能以此方式获取,但这种单纯的密码登录也不安全。
A网站用户获取某个网站资源的权力,但却没有限制获取的范围和期限。
当用户修改密码的时候,就会收回A网站的权力,但是这样做,会使得其他所有获得用户授权的A应用程序全部失效。
只要有一个A应用程序被破解,就会导致用户密码泄漏,以及所有被密码保护的数据泄漏。
因此,这种方式是不安全的,所以为了解决这种问题,OAuth就解决了这种问题。
允许用户让第三方A应用访问该用户在B网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。就比如我用QQ登录博客园,那博客园(第三方应用)的昵称就可以是我的QQ(某网站)昵称,它获取到了我的QQ昵称,并存到了博客园的数据库,我以后就一直可以使用QQ来登录博客园,但是博客园却不知道我QQ的用户名和密码。
3.1.2 说明
OAuth在"客户端"与"服务提供商"之间,设置了一个授权层(authorization layer)。"客户端"不能直接登录"服务提供商",只能登录授权层,以此将用户与客户端区分开来。"客户端"登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。
"客户端"登录授权层以后,"服务提供商"根据令牌的权限范围和有效期,向"客户端"开放用户储存的资料。
(A)用户打开客户端以后,客户端要求用户给予授权。(B)用户同意给予客户端授权。(C)客户端使用上一步获得的授权,向认证服务器申请令牌。(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。(E)客户端使用令牌,向资源服务器申请获取资源。(F)资源服务器确认令牌无误,同意向客户端开放资源。
3.1.3 模式
用户怎样实现客户端授权,所以需要通过不同的授权模式让客户端可以获取令牌,进而获取资源。因此,客户端获取授权常用的模式如下:
后续篇章会对这些模式进行说明和搭建应用项目。
3.2 OpenID Connect
OpenID Connect是基于OAuth 2.0规范族的可互操作的身份验证协议。它使用简单的REST / JSON消息流来实现,和之前任何一种身份认证协议相比,开发者可以轻松集成。
OpenID Connect允许开发者验证跨网站和应用的用户,而无需拥有和管理密码文件。
OpenID Connect允许所有类型的客户,包括基于浏览器的JavaScript和本机移动应用程序,启动登录流动和接收可验证断言对登录用户的身份。
进一步来说:
OpenID Connect是OAuth 2.0协议之上的简单身份层,用 API 进行身份交互的框架,允许客户端根据授权服务器的认证结果最终确认用户的身份,以及获取基本的用户信息;
它支持包括Web、移动、JavaScript在内的所有客户端类型;
它是可扩展的协议,允许你使用某些可选功能,如身份数据加密、OpenID提供商发现、会话管理;
OpenID Connect vs OpenID 2.0:OpenID Connect完成很多与OpenID 2.0(即认证,对用户的身份进行认证,判断其身份是否有效)相同的任务,是API-friendly,定义了可选的签名和加密的机制;
OAuth 1.0和OpenID 2.0的集成需要扩展,而OpenID Connect协议本身就建立在OAuth 2.0之上。
(身份验证)+ OAuth 2.0 = OpenID Connect
因此,OpenID Connect 是“认证”和“授权”的结合。
我们经常会混淆OpenID和OAuth协议之间的关系,下文会对这两者进行区分说明。
为什么开发者要使用OpenID Connect?
因为它很简单,可靠,安全,并让他们摆脱困难和危险的存储和管理别人的密码。也有好处,它让用户的生活更容易在网站注册和注册从而减少遗弃。
区别
4.1 OAuth 与 OpenID
首先,来认识两个英文单词,也是我们在平时中很容易混淆的。
authorization : n. 授权,认可;批准,委任。
authentication : n. 证明;鉴定;证实。
而在认证授权服务中,也应用了这两个单词的表面意思。
OpenID 是一个以用户为中心的数字身份识别框架,它具有开放、分散性。OpenID 的创建基于这样一个概念:我们可以通过 URI (又叫 URL 或网站地址)来认证一个网站的唯一身份,同理,我们也可以通过这种方式来作为用户的身份认证。
OpenID : 是Authentication,即认证,对用户的身份进行认证,判断其身份是否有效,也就是让网站知道“你是你所声称的那个用户”。
侧重的是authentication:即证明 “用户是谁?”
OAuth : 是Authorization,即授权,在已知用户身份合法的情况下,经用户授权来允许某些操作,也就是让网站知道“你能被允许做那些事情”。
侧重的是authorization :即授权 “用户能做什么?”
由此可知,授权要在认证之后进行,只有确定用户身份只有才能授权。
4.1.1 场景
OpenID 是证实身份(Authentication)作用的,就好比我们参加大型考试一下,进考场的时候,监考官需要我们拿出身份证和准考证来检验,比对是否是同一个人。这个过程就是在验证 “身份,这就是我”,同时也证实了这不是一个匿名伪造的不可信任信息。考官比对身份成功后,就会进一步询问。
比如我用 Google 的 OpenID 服务登录 xxx.com , xxx.com 先把我导向 Google 的授权页面,我使用 Google 帐号 test@gmail.com 登录并同意后,页面跳回 xxx.com , xxx.com 拿到了我的“唯一标识”,这个唯一标识可能是 abbcccxxxxxxxddccddxxxx11 ,xxx.com 从这个字符串里无法获得任何 xxx@gmail.com 的个人信息(甚至连邮箱地址也不知道), xxx.com 只知道以后只要使用谷歌登录并返回 abbcccxxxxxxxddccddxxxx11 这个标识符,那就是我在登录。
但是如果你想在认证过程中获得用户的其他信息(比如手机号等 )就得多做一步了。
OAuth 是关于授权、许可(Authorization)的,当考官看完比对你的身份后,还要求掏出兜里的东西,拿出随身携带里的东西、手机等随身物品以便检查,检查你是否携带考场违规物品,这时就需要得到被检查人的许可才行,被检查人有权利扭头就走,但要想进场考试,必须给予许可、配合检查。这是在回答「我同意让你对我进一步做些什么」,是为了在被授予权限的前提下,更多的获取除了个人信息以外,身上携带的东西是否包含违规物品。(如:手机,计算器,手表,非指定文具等)
我想通过微博登录 xxx.com ,xxx.com 要先把我 redirect 到新浪微博的授权页面,我通过微博帐号登录并授权后,页面跳回 xxx.com ,xxx.com 拿到我的访问 token 后还要再调用一个接口来获得我的会员 UID ,这个 UID 就是新浪用户的“唯一标识”了。
# 借鉴网友的说明: 如今越来越多的网站,以及一些应用程序都开始使用第三方社交平台账户登录,那这里就会涉及到安全性的问题,隐私的问题,你不能随意来获取我的资料,当然你来使用我的资料,你要经过用户的同意,那这个用户是不是我平台上,还是要来向我求证,那在这个过程中,实际上就出现了两个过程,我们还是直接使用上次的例子来说明,比较直观,博客园使用QQ登录,进入博客园的登录页,点击使用QQ登录:在进入到QQ登录界面后,最开始是要请求认证,用户输入QQ号和密码,点击登录,腾讯互联会先进行验证该用户是否为我的用户,如果是我的用户,那么我会通知你(博客园),他是我的用户,你可以使用该账户登录你的系统,这个过程就是认证(Authentication),认证就是证明你是谁,你是否是真实存在的,就好像,快递员来给你送快递,让你出示你的身份证,他确定你是本人后,把快递给你,这就是OpenID。而在QQ授权登录下方,有两给CheckBox复选框,可以允许博客园获得您的昵称、头像、性别,这是在认证之后的事了,在腾讯互联你是我平台的用户后,你可以自己选择博客园是否有权去获取你的相关信息,当你勾选后,腾讯互联就把你的这些基本信息给了博客园,这个过程就是授权(Authorization),授权就是确定了你是谁后,又把属于你的东西给了别人,犹如你向快递员出示了身份证,然后你又把你房门的密码给了他,并告诉他说,我把房门密码给你,你帮我放到我客厅里吧。
可以看出,OAuth 相对于 OpenID 最大的区别就是,网站在认证授权的过程中实际上是拿到了你的帐户访问权限继而确认你的身份,但是这同时也存在一个安全隐患,因为网站在拿到你的“唯一标识”的同时还拿到了一把你的账户的 “临时钥匙”。但是你不知道网站会不会拿这把钥匙“干坏事”,这个只有站长心里清楚。同时 OAuth 还比 OpenID 多了几个额外的请求步骤,登录所费时间一定是长于 OpenID 的。
4.2 OAuth、OpenID 与 OpenID Connect
OpenID Connect 因为其基于OAuth协议(可以看上文OAuth说明),所以OpenID-Connect协议中也包含了client_id、client_secret还有redirect_uri等字段标识。这些信息被保存在“身份认证服务器”,以确保特定的客户端收到的信息只来自于合法的应用平台。这样做是目的是为了防止client_id泄露而造成的恶意网站发起的OIDC流程。
OpenID Connect完成很多与OpenID 2.0 相同的任务,是API-friendly,定义了可选的签名和加密的机制。
OAuth 1.0 和 OpenID 2.0 的集成需要扩展,而OpenID Connect协议本身就建立在OAuth 2.0之上。
因此,OpenID Connect 是“认证”和“授权”的结合。
(身份验证)+ OAuth 2.0 = OpenID Connect (OIDC) = ( Authentication + Authorization + OAuth2.0)
简要而言,OIDC是一种安全机制,用于应用连接到身份认证服务器(Identity Service)获取用户信息,并将这些信息以安全可靠的方法返回给应用。
# 借鉴网友说明
举个例子。某个用户使用*Facebook*应用*“What online quiz best describes you?”* ,该应用可以通过*Facebook*账号登录,则你可以在应用中发起请求到“身份认证服务器”(也就是Facebook的服务器)请求登录。这时你会看到界面,询问是否授权。在 OAuth 中,这些授权被称为scope。OpenID-Connect也有自己特殊的scope--openid ,它必须在第一次请求“身份鉴别服务器”(Identity Provider,简称IDP)时发送过去。
4.3 JWT 与 OAuth2 .0
要比较JWT和OAuth2,首先要明白一点就是,这两个根本没有可比性,是两个完全不同的东西。
但是既然是没有可比性,为何还要放一块比较呢?实际开发应用中,就发现很多拿 JWT和OAuth2.0 作对比,很多情况下,在讨论OAuth2的实现时,会把JSON Web Token作为一种认证机制使用。这也是为什么他们会经常一起出现。
4.3.1 内容区别
JWT是一种认证协议 JWT提供了一种用于发布接入令牌(Access Token),并对发布的签名接入令牌进行验证的方法。令牌(Token)本身包含了一系列声明,应用程序可以根据这些声明限制用户对资源的访问。
一个token包含三部分:header、claims、signature
OAuth2是一种安全的授权框架
提供了一套详细的授权机制。用户或应用可以通过公开的或私有的设置,授权第三方应用访问特定资源。
Oauth2定义了一组想当复杂的规范。涉及到:Roles角色、Client Types客户端类型、Client Profile客户端描述、Authorization Grants认证授权、Endpoints终端等。
4.3.2 场景区别
jwt应用场景
1)无状态的分布式API
JWT的主要优势在于使用无状态、可扩展的方式处理应用中的用户会话。服务端可以通过内嵌编码的声明信息,很容易地获取用户的会话信息,而不需要去访问用户或会话的数据库。但是,如果系统中需要使用黑名单实现长期有效的token刷新机制,这种无状态的优势就不明显了。
Oauth2应用场景
1)第三方认证服务器
2)大型企业解决方案
API的使用依赖于外部的第三方认证提供者。去认证服务商 那里注册你的应用,然后设置需要访问的用户信息,比如电子邮箱、姓名等。当用户访问站点的注册页面时,会看到连接到第三方认证提供商的入口。用户点击以后被重定向到对应的认证服务商网站,获得用户的授权后就可以访问到需要的信息,然后重定向回来你的应用中。
4.3.3 归纳说明
Oauth2和JWT是完全不同的两种东西,一个是授权认证的框架,另一种则是认证验证的方式方法。OAuth2不像JWT一样是一个严格的标准协议,因此在实施过程中更容易出错。
两种方案都需要SSL安全保护,也就是对要传输的数据进行加密编码。安全地传输用户提供的私密信息,在任何一个安全的系统里都是必要的。否则任何人都可以通过侵入网络,在用户登录的时候窃取用户的用户名和密码等信息。
总结
本篇主要是对Identity Server4的说明,认识到是一个基于OpenID Connect协议标准的身份认证和授权程序。
简单的涉及对基础知识的认识以及区别说明,从OAuth、OpenID、OpenID Connect以及JWT等进行对比区别说明。
在后续中会对Identity Server4中常用术语说明,多种授权模式,数据库持久化以及UI界面优化和常见问题,搭建一个完整可用的认证授权项目。
如果有不对的或不理解的地方,希望大家可以多多指正,提出问题,一起讨论,不断学习,共同进步。
资料
Identity Server 官方文档
JSON Web Token
理解OAuth 2.0
Identity Server 授权类型