1.概述
OAUTH,Open Authorization,开放授权协议,为用户资源的授权提供了一个安全的、开放而又简易的标准。目的是让第三方对用户的数据只有有限访问权,而无法触及到用户的核心信息。
例如,在第三方网站上使用微信或者QQ作为账号进行登录,就是使用的oauth协议,只返回给第三方诸如用户名、头像等信息,而不会返回给第三方秘密等核心数据。
OAuth最初由Twitter的开发人员提出,后来成为了一个互联网标准,并得到了广泛应用。OAuth2.0是OAuth协议的第二个版本,是一种更加安全、可扩展、功能更加完备的授权协议。目前我们说OAuth一般指的就是OAuth 2.0。
2.流程
oauth 2.0的流程概括起来很简单,就是客户端先去认证服务器通过认证获取一个token,然后用这个token去资源服务器拿资源。
oauth 2.0将整个协议中的实体分为四种:
资源拥有者
客户端
认证服务器
资源服务器
资源拥有者(拥有资源服务器上资源的用户),通过客户端去授权服务器上进行授权,获取token,用token去资源服务器上获取资源。
当然以上分工只是理论上的,实际应用中很多时候授权服务器和资源服务器是放在一起的。
举个例子,通过QQ登录CSDN,我们在CSDN登录页上输入的这个QQ用户就是资源拥有者,他拥有QQ的资源服务器上的资源,我们输入完QQ用户信息后,发送请求到QQ的认证服务器进行鉴权,认证服务器认证成功后返回一个token,CSDN再用这个token去QQ的资源服务器上获取有限资源,如除开密码等敏感数据之外的用户名、头像之类的数据。
3.客户端注册
在oauth 2.0中出于安全考虑,不是所有客户端都能进行授权的。因为怕诸如CSRF之类的攻击,能进行授权的客户端必须是在“名单”内的客户端,也就是说授权的前提是客户端要去注册。每个客户端注册的时候需要以下信息:
应用名,客户端的名称
首页,客户端的首页地址
回调页,当授权成功后转跳的页面
客户端ID(client ID)
密钥(secret key)
这里面client ID和secret key尤其重要,前者是每种客户端的唯一标识,后者是用于数据加密。
4.授权模式
授权模式(Authorization Grant)是指 OAuth 协议中规定的用于获取访问令牌的一种方式。前文所描述的通过token去获取资源只是一种笼统概述性的说法,其实细说的话oauth 2.0中有四种授权方式:
授权码模式
简化模式
密码模式
客户端模式
4.1.授权码模式
(1)客户端携带自己的身份信息重定向到授权界面(平时使用QQ登录三方应用时弹出的那个QQ的登录页面)
(2)用户在授权界面上进行用户认证(输入用户名、密码)
(3)如果认证成功,返回授权码,重定向到指定的页面
(4)客户端通过授权码去拿token。
由于授权浏览器(登录页)是在资源提供方,资源拥有者进行用户认证时是最安全的。联想一下平时我们用QQ或者微信登录第三方应用时,弹出来的腾讯官方的登陆页面,在这上面录入我们的验证信息是十分安全的。
授权码模式中一次认证需要请求授权服务器三次,这三次里分别会携带不同的参数:
在(1)步之前,客户端向授权服务器请求授权界面的时候,会在请求中携带如下参数:
参数 | 作用 |
client_id | 客户端准入标识 |
response_type | 授权码模式固定为code。 |
scope | 客户端的权限 |
edirect_uri | 授权码申请成功后的转跳地址 |
第(2)步用户认证授权阶段,除了上述基本参数外,请求里还会带有username、password。
到了第(4)步通过授权码拿令牌的时候,请求里面会携带如下参数:
参数 | 作用 |
client_id | 客户端准入标识 |
response_type | 授权码模式固定为code。 |
scope | 客户端的权限 |
edirect_uri | 授权码申请成功后的转跳地址 |
grant_type | 授权类型,填写authorization_code,表示授权码模式 |
code | 授权码 |
4.2.简化模式
简化模式是基于授权码模式的简化,在返回授权码的那一步,直接返回的就是token。授权服务器将授权码将令牌(access_token)以Hash的形式存放在重定向uri的fargment中发送给浏览器。
简化模式请求格式,携带的参数和授权模式中对应步骤是一模一样的。
4.3.密码模式
资源拥有者将自己的用户名/密码发给客户端,客户端通过资源拥有者的用户名/密码来获取token。
在密码模式中一次授权需要请求一次授权服务器:
第(2)步里的请求中会携带如下参数:
参数 | 作用 |
client_id | 客户端准入标识 |
client_secret | 客户端秘钥,用于客户端进行身份验证,保证其合法性。注意,该参数只在保密客户端(Confidential Client)的情况下需要传递。公开客户端(Public Client)不需要传递该参数 |
grant_type | 授权类型,此处应该设置为"password" |
username | 资源拥有者用户名 |
password | 资源拥有者密码 |
4.4.客户端模式
这种认证模式不需要资源拥有者的参与,直接由客户端来获取token,这就要求资源提供方对client完全的信任,而client本身也是安全的。
在客户端模式中,一次授权需要请求一次授权服务器。
在第(1)步中,会在请求中携带如下参数:
参数 | 说明 |
grant_type | 授权类型,此处应该设置为"client_credentials"。 |
client_id | 客户端ID,用于标识客户端应用程序。 |
client_secret | 客户端秘钥,用于客户端进行身份验证,保证其合法性。注意,该参数只在保密客户端(Confidential Client)的情况下需要传递。公开客户端(Public Client)不需要传递该参数。 |
4.5.优缺点总结
1.授权码模式
优点:安全性高,因为授权码只有一次性有效,且在传输过程中被加密。还能通过客户端密钥验证客户端的合法性,确保安全性。
缺点:需要在客户端和授权服务器之间建立额外的交互,使得实现起来比较复杂。
适用场景:适用于需要高安全性保护的客户端应用程序,比如Web应用程序或移动应用程序。
2.简化模式
优点:实现简单,因为它不需要客户端来保护授权码的安全性。
缺点:安全性相对较低,因为令牌直接传递给客户端,而没有通过授权码的方式进行保护。
适用场景:适用于具有低风险性的客户端应用程序,比如JavaScript应用程序或移动应用程序。
3.密码模式
优点:实现简单,因为只需要客户端和资源服务器之间进行交互,不需要授权服务器的参与。
缺点:安全性较低,因为客户端需要直接处理用户的凭证,可能会导致用户凭证泄露的风险。
适用场景:适用于具有高信任级别的客户端应用程序,比如私有API或管理应用程序。
4.客户端模式
优点:实现简单,因为只需要客户端进行身份验证,无需用户的参与。
缺点:安全性相对较低,因为令牌直接传递给客户端,而没有通过授权码的方式进行保护。
适用场景:适用于具有低风险性的客户端应用程序,比如API监视程序或公开API。