单点登录与OAuth2.0简介
Posted 飞鹰技术
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单点登录与OAuth2.0简介相关的知识,希望对你有一定的参考价值。
单点登录(SSO,Single Sign On):是在多个应用系统中,用户只需登录一次就可以访问所有相互信任的应用系统。在此过程中就会涉及到认证与授权(详情参见:):
认证(authentication): 证明是谁;
授权(authorization): 可访问哪些资源,有哪些权限;
单点登录
单点登录在现在的系统架构中广泛应用,他将多个子系统的认证体系打通,实现了一个入口多处使用。
当用户首次访问系统时,因还未登录,会被引导到认证系统中进行登录认证;认证系统根据用户提供的登录信息进行身份校验,若通过校验,则返回一个认证的凭据(ticket);后续用户即可通过此ticket访问应用系统,应用系统访问验证服务器对ticket行校验,检查其合法性。
访问服务:SSO客户端发送请求访问应用系统提供的服务资源。
定向认证:SSO客户端会重定向用户请求到SSO服务器。
用户认证:用户身份认证。
发放票据:SSO服务器会产生一个认证的Ticket。
验证票据:SSO服务器验证票据Ticket的合法性,验证通过后,允许客户端访问服务。
传输用户信息:SSO服务器验证票据通过后,返回认证结果信息给客户端。
要实现SSO,需要以下主要的功能:
所有应用系统共享一个身份认证系统。统一的认证系统是SSO的前提之一。
认证系统的主要功能是对用户进行登录认证;认证成功后,认证系统应该生成统一的认证标志(ticket),返回给用户。
认证系统要能对ticket的有效性进行效验。
所有应用系统能够识别和提取ticket信息:要实现SSO的功能,应用系统要能对ticket进行识别和提取,通过与认证系统的通讯,能自动判断当前用户是否登录过,从而完成单点登录的功能。
OAthen2简介
OAuth2是一个授权的开放网络标准(RFC6749),它可以使第三方应用程序或客户端获得对HTTP服务上(如,微博、微信 )用户帐户信息的有限访问权限。OAuth2通过将用户身份验证委派给托管用户帐户的服务以及授权客户端访问用户帐户进行工作。
OAuth2角色
资源所有者(Resource Owner):即资源的提供者,允许授权用户进行访问;
资源服务器(Resource Server):托管了受保护的账户信息;
授权服务器(Authorization Server):验证用户身份,然后提供资源访问令牌;
客户端(Client):访问受限资源的第三方应用;
授权流程
OAuth通过引入授权层以及分离客户端角色和资源所有者角色来解决传统Client-Server身份验证模型中存在的问题。在保证安全的情况下,允许第三方通过授权凭证来访问受限资源。
客户端在请求受保护资源时,先获得一个访问令牌(由授权服务器在资源所有者许可的情况下颁发),客户端使用访问令牌访问托管在资源服务器的受保护资源。
实际的授权流程会因授权许可类型的不同而不同,但主要抽象流程如上图所示:
Authrization Request:客户端向用户请求对资源服务器授权。如‘以微博账户登录’;
2.Authorization Grant(Get):初次申请时,需要用户授权‘允许’。
3.Authorization Grant(Post):用户授权后,客户端会向授权服务器发送它自己的客户端身份标识和上一步中的authorization grant,请求访问令牌。
Access Token(Get):认证通过后,授权服务器将为客户端派发access token。授权阶段至此全部结束。
Access Token(Post && Validate):客户端向资源服务器发送access token用于验证并请求资源信息。
Protected Resource(Get):如果access token验证通过(令牌有效,且在有效期内),资源服务器将向客户端返回资源信息。
授权许可
授权许可是一个代表资源所有者授权(访问受保护资源)的凭据,客户端用它来获取访问令牌。有四种许可类型(授权码、隐式许可、资源所有者密码凭据和客户端凭据):
授权码(Authorization Code):最常用的授权许可类型(QQ、微博等)。授权服务器做为客户端与资源所有者的中介,客户端不是直接从资源所有者请求授权,而是引导资源所有者至授权服务器(由在RFC2616中定义的用户代理),授权服务器之后引导资源所有者带着授权码回到客户端。
在引导资源所有者携带授权码返回客户端前,授权服务器会鉴定资源所有者身份并获得其授权。由于资源所有者只与授权服务器进行身份验证,所以资源所有者的凭据不需要与客户端分享。
授权码提供了一些重要的安全益处,例如验证客户端身份的能力,以及向客户端直接的访问令牌的传输而非通过资源所有者的用户代理来传送它(以避免潜在暴露给他人)。
Authorization Request
GET /authorize?response_type=code&client_id=1&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Foauth2&scope=user, photo HTTP/1.1
Host: server.example.com
Authorization Response
HTTP/1.1 302 Found
Location: https://client.example.com/oauth2?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz
Access Token Request(Code要为上面Response中返回的)
POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&client_id=1&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Foauth2
Access Token Response
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter":"example_value"
}
隐式许可(Implicit):是Authorization Code的简化版本。省略了颁发授权码(Authorization Code)给客户端的过程,直接返回访问令牌和可选的刷新令牌。
适用于没有Server服务器来接受处理Authorization Code的第三方应用。
提高了一些客户端(例如一个作为浏览器内应用实现的客户端)的响应速度和效率,因为它减少了获取访问令牌所需的往返数量。
便利应该和采用隐式许可的安全影响作权衡(更容易被中间人攻击)。
资源所有者密码凭据(Resource Owner Password Credentials Grant):再进一步的简化,Client直接使用Resource owner提供的username和password来直接请求access_token(直接发起Access Token Request然后返回Access Token Response信息)。
这种模式一般适用于Resource server高度信任第三方Client的情况下。
客户端凭据(Client Credentials Grant):更加简化,Client直接以自己的名义而不是Resource owner的名义去要求访问Resource server的一些受保护资源。
认证服务器不提供像用户数据这样的重要资源,仅仅是有限的只读资源或者一些开放的API。
需要开发者提前向开放平台申请,成功对接后方能使用。
Authorization Request
GET /authorize?response_type=token&client_id=1&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Foauth2&scope=user,photo HTTP/1.1
Host: server.example.com
Access Token Response
HTTP/1.1 302 Found
Location: http://client.example.com/oauth2#access_token=2YotnFZFEjr1zCsicMWpAA&state=xyz&expires_in=3600
Request(Response与前面同)
POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=password&username=blackheart&password=1234
Request(Response与前面同)
POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
授权码方式获取令牌的过程:
A、Client通过URL(认证服务器提供)访问(通过浏览器等)Authorization Server;需提供:客户端标识、请求范围、本地状态、重定向URL等参数;
B、Authorization Server验证A步骤中提供的参数;若正确,则提供一个页面用于登录Resource Owner,登录成功后选择可访问的资源与权限;
C、B步骤无误后返回一个授权码(Authorization Code)给Client;
D、Client拿着C步骤返回的授权码和客户端标识、重定向URL等信息作为参数,请求Authorization Server提供的URL以获取访问令牌;
E、Authorization Server返回访问令牌和可选的刷新令牌以及令牌有效时间等信息给Client。
令牌
访问令牌:访问受保护资源的凭据。访问令牌是一个代表向客户端颁发的授权的字符串。该字符串通常对于客户端是不透明的。
令牌代表了访问权限的由资源所有者许可并由资源服务器和授权服务器实施的具体范围和期限。
令牌可以表示一个用于检索授权信息的标识符或者可以以可验证的方式自包含授权信息(即令牌字符串由数据和签名组成)。
访问令牌提供了一个抽象层,用单一的资源服务器能理解的令牌代替不同的授权结构(例如,用户名和密码)。这种抽象使得颁发访问令牌比颁发用于获取令牌的授权许可更受限制,同时消除了资源服务器理解各种各样身份认证方法的需要。
刷新令牌:由授权服务器颁发给客户端,用于在当前访问令牌失效或过期时,获取一个新的访问令牌,或者获得相等或更窄范围的额外的访问令牌(访问令牌可能具有比资源所有者所授权的更短的生命周期和更少的权限)。
刷新令牌是一个代表由资源所有者给客户端许可的授权的字符串。该字符串通常对于客户端是不透明的。
该令牌表示一个用于检索授权信息的标识符。不同于访问令牌,刷新令牌设计只与授权服务器使用,并不会发送到资源服务器。
应用注册
为使用授权服务器,必须先向授权服务器提供方(如,微博)注册我们的应用。注册时一般至少需要提供:应用名称、网站、重定向/回调URL。
应用注册成功后,授权方服务将以client id和client secret的形式为应用发布client credentials(客户端凭证)。client id是公开透明的字符串,授权方服务使用该字符串来标识应用程序,并且还用于构建呈现给用户的授权 url 。当应用请求访问用户的帐户时,client secret用于验证应用身份,并且必须在客户端和服务之间保持私有性。
接口认证Bearer Token
Bearer Token (RFC 6750) 用于OAuth 2.0授权访问资源,任何Bearer持有者都可以无差别地用它来访问相关的资源,而无需证明持有加密key。
一个Bearer代表授权范围、有效期,以及其他授权事项;
一个Bearer在存储和传输过程中应当防止泄露,需实现Transport Layer Security (TLS);
一个Bearer有效期不能过长,过期后可用Refresh Token申请更新。
资源请求方式
Bearer实现资源请求有三种方式:Authorization Header、Form-Encoded Body Parameter、URI Query Parameter,这三种方式优先级依次递减
Authorization Header:该头部定义与HTTP规范中所制定的Basic Auth方案类似:
GET /resource HTTP/1.1
Host: server.example.com
Authorization: Bearer mF_9.B5f-4.1JqM
Form-Encoded Body Parameter: 在客户端无法使用Authorization请求头情况下,才使用该方法发送Bearer;使用该方法发送Bearer须满足如下条件:
头部必须包含"Content-Type: application/x-www-form-urlencoded";
entity-body必须遵循application/x-www-form-urlencoded编码;
若entity-body除access_token之外,还有其他参数,须以"&"分隔开;
entity-body只包含ASCII字符;
要使用request-body已经定义的请求方法,不能使用GET;
POST /resource HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
access_token=mF_9.B5f-4.1JqM
URI Query Parameter: 服务端应在响应中使用 Cache-Control: private
GET /resource?access_token=mF_9.B5f-4.1JqM HTTP/1.1
Host: server.example.com
Cache-Control: no-store
WWW-Authenticate头
客户端未发送有效Bearer的情况下(即错误发生时),资源服务器须发送WWW-Authenticate头:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="example", error="invalid_token", error_description="The access token expired"
WWW-Authenticate字段的用法(下列这些属性/指令不应重复使用):
Bearer:标识认证类型(基于OAuth 2.0);
realm:与Basic、Digest一样,B标识域定义;
scope:授权范围,可选的,大小写敏感的,空格分隔的列表。OAuth 2.0还规定客户端发送scope请求参数以指定授权访问范围,而在实际授权范围与客户端请求授权范围不一致时,授权服务器可发送scope响应参数以告知客户端下发的token实际的授权范围。下为两个scope用法实例:
scope="openid profile email"
scope="urn:example:channel=HBO&urn:example:rating=G,PG-13"
error:描述访问请求被拒绝的原因;
error_description:向开发者提供一个可读的解释;
error_uri:absolute URI,标识人工可读解释错误的页面;当错误发生时,资源服务器将发送的HTTP Status Code(通常是400, 401, 403, 或405)及Error Code如下:
invalid_request:请求丢失参数,或包含无效参数、值,参数重复,多种方法发送access token,畸形等。资源服务器将发送HTTP 400 (Bad Request)
invalid_token:access token过期、废除、畸形,或存在其他无效理由的情况。资源服务器将发送HTTP 401 (Unauthorized),而客户端则需要申请一个新的access token,然后才能重新发送该资源请求;
insufficient_scope:客户端提供的access token的权限太低。资源服务器将发送HTTP 403 (Forbidden),同时WWW-Authenticate头包含scope属性,以指明需要的权限范围;
Token Response示例
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"mF_9.B5f-4.1JqM",
"token_type":"Bearer",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA"
}
以上是关于单点登录与OAuth2.0简介的主要内容,如果未能解决你的问题,请参考以下文章