标签:blog http io ar os 使用 sp strong on
web:http://oauth.net/2/
rfc:http://tools.ietf.org/html/rfc6749
doc:http://oauth.net/documentation/
code:http://oauth.net/code/
之前做过微信公众平台,基本流程参照文档,也没有太注意OAuth太多细节,最近在与携程会员对接,陆陆续续折腾好几天吧,就花了一点时间研究了下OAuth协议,感觉OAuth大行其道路,得益于微博的推广,另外OAuth与OpenID是比较容易混淆的两个东西,OpenID设计的目的趋向与身份校验,OAuth设计的目的是对用户的资源授权。现阶段一般互联网公司应该都支持OAuth2协议,如新浪,阿里,腾讯等,特点是都拥有大量的用户群,来等待其他开发者与第三方应用的接入,如现在比较火爆的微信公众平台。
OAuth2.0是一个开放协议,允许用户让第三方应用以安全且标准的方式获取该用户在某一网站、移动或桌面应用上存储的私密的资源(如用户个人信息、照片、视频、联系人列表),而无需将用户名和密码提供给第三方应用。
OAuth 2.0是OAuth协议的下一版本,但不向后兼容OAuth 1.0。 OAuth 2.0关注客户端开发者的简易性,同时为Web应用,桌面应用和手机,和起居室设备提供专门的认证流程。
OAuth 允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要分享他们的访问许可或他们数据的所有内容。
上面是比较官方的描述,简单些就是OAuth2是由OAuth1.0发展而来,两者不向后兼容,支持多平台设备。可以使用自己的账户与密码授权来让第三方应用在特定的时间内获得用户的资源信息。以新浪围脖为例,比如我习惯用微博登录一些社交网站,这样发现有意思的东西,可以快速分享到微博上,嗯,我经常这么干。按照流程一般先需要用户到新浪上去授权,登录成功后,在知乎上就可以获得微博上的头像与用户基本信息等。
在讲述OAuth2.0之前先得了解基本授权的基本术语:
资源拥有者(resource owner):能授权访问受保护资源的一个实体,如新浪微博用户 irving;
资源服务器(resource server):存储受保护资源,客户端通过access token请求资源,资源服务器响应受保护资源给客户端;存储着用户irving的微博等信息。
授权服务器(authorization server):成功验证资源拥有者并获取授权之后,授权服务器颁发授权令牌(Access Token)给客户端。
客户端(client):如新浪微博第三方应用,也可以是它自己的官方应用;其本身不存储资源,而是资源拥有者授权通过后,使用它的授权(授权令牌)访问受保护资源,然后客户端把相应的数据展示出来。“客户端”术语不代表任何特定实现(如应用运行在一台服务器、桌面、手机或其他设备)。
+--------+ +---------------+ | |--(A)- Authorization Request ->| Resource | | | | Owner | | |<-(B)-- Authorization Grant ---| | | | +---------------+ | | | | +---------------+ | |--(C)-- Authorization Grant -->| Authorization | | Client | | Server | | |<-(D)----- Access Token -------| | | | +---------------+ | | | | +---------------+ | |--(E)----- Access Token ------>| Resource | | | | Server | | |<-(F)--- Protected Resource ---| | +--------+ +---------------+ Figure 1: Abstract Protocol Flow
客户端必须得到用户的授权(authorization grant),才能获得令牌(access token)。OAuth 2.0定义了四种授权方式。
因为一般授权码的使用的比较多,客户端可能会使用简化模式或客户端模式,我这里只简述授权码模式,授权码流程
+----------+ | Resource | | Owner | | | +----------+ ^ | (B) +----|-----+ Client Identifier +---------------+ | -+----(A)-- & Redirection URI ---->| | | User- | | Authorization | | Agent -+----(B)-- User authenticates --->| Server | | | | | | -+----(C)-- Authorization Code ---<| | +-|----|---+ +---------------+ | | ^ v (A) (C) | | | | | | ^ v | | +---------+ | | | |>---(D)-- Authorization Code ---------‘ | | Client | & Redirection URI | | | | | |<---(E)----- Access Token -------------------‘ +---------+ (w/ Optional Refresh Token) Note: The lines illustrating steps (A), (B), and (C) are broken into two parts as they pass through the user-agent. Figure 3: Authorization Code Flow
(A)用户授权访问认证服务器
(B)用户选择是否给予客户端授权
(C)如果给予授权,认证服务器(authorization service)将重定向(http状态码302)到A流程中给予的URL(redirect_uri),同时附上一个授权码(code)
(D)客户端收到授权码(code),向认证服务器(authorization service)申请令牌(发送post请求)。这个过程是在客户端的后台请求上完成的,对用户不可见
(E)认证服务器检查授权码(code)和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)以及失效时间(expires_in)
如新浪的授权流程图:
1、客户端从资源拥有者给予授权
比如我现在使用新浪微博的账户授权登录知乎。
GET /oauth/auth/sina?next=/oauth/account_callback HTTP/1.1
Host: www.zhihu.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://www.zhihu.com/请求包含以下参数:
- response_type:表示授权类型,必选项,此处的值固定为"code"
- client_id:表示客户端的ID,必选项
- redirect_uri:表示重定向URI,可选项
- scope:表示申请的权限范围如 user,order,可选项
- state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。
一般开发一个基于新浪微博app的第三方应用,需要申请appkey和appsecret分别对应OAuth2.0中的client_id与client_secret,可能一些服务端会扩展一些其他的名称,腾讯就是这个干的。
2、用户同意给予客户端授权
分两种情况,如果是没有微博登录成功的会话,就让用户登录,如上图如果之前我已经有了登录成功的会话了,这个时候就让用户确认同意授权(知乎好流氓,直接略了这一步,但是流程还是一样的),我用其他网站的联合登录截了个图如下。
CONNECT api.weibo.com:443 HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0
Connection: keep-alive
Connection: keep-alive
Host: api.weibo.com:443
后面我使用Fiddler抓了下包流程还是一样的,还是一样会302跳转,另外发现还使用了socketio,貌似服务端有基于NodeJS的服务。
GET /socket.io/1/?t=1417252232035 HTTP/1.1
Host: comet.zhihu.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://www.zhihu.com/
Origin: http://www.zhihu.com
Connection: keep-alive
返回:
HTTP/1.1 200 OK
Server: zhihu_nginx
Date: Sat, 29 Nov 2014 09:11:19 GMT
Content-Type: text/plain
Connection: keep-alive
Vary: Accept-Encoding
Access-Control-Allow-Origin: http://www.zhihu.com
Access-Control-Allow-Credentials: true
Content-Length: 36rfmX2x_OC9aKyzZAGh3c:60:60:websocket
GET /oauth/auth/request_sina_token?next=%2Foauth%2Faccount_callback&state=78db9a8b58b2dab6970d4520907ad629&code=879c3a9aabdf5dfe69b92092204fe480 HTTP/1.1
Host: www.zhihu.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://www.zhihu.com/
Connection: keep-alive授权成功返回如下参数:
- code:表示授权码,必选项。通常授权码只能使用该码一次,并且会设置有效时间。
- state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。
3、客户端使用授权码向认证服务器申请令牌。
这个过程发生在客户端后台,用户不可见,这也是授权码模式的特性,更安全。大致接口地址类似(服务端会验证client_id、client_secret、auth code的正确性或更新令牌 refresh_token):
http://localhost:8080/oauth2/access_token?client_id={AppKey}&client_secret={AppSecret}&grant_type=authorization_code&redirect_uri={YourSiteUrl}&code={code}
向认证服务器申请令牌包含以下参数:
- grant_type:表示使用的授权模式,必选项,此处的值固定为"authorization_code"。
- code:表示上一步获得的授权码,必选项。
- redirect_uri:表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致。
- client_id:表示客户端ID,必选项
- client_secret:表示客户端密钥,必选项。
4、如果授权码验证成功,则下生成一个令牌。
这个过程发生在服务端后台,服务端会验证client_id、client_secret、auth code的合法性,成功则生成一个令牌。
认证服务器返回,包含以下参数:
5、客户端使用访问令牌向资源服务器请求受保护资源。
客户端实现,请求用户保护的资源。
知乎成功后返回:
GET /oauth/account_callback?callbacktype=sina HTTP/1.1
Host: www.zhihu.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://www.zhihu.com/
Connection: keep-alive
6、资源服务器验证访问令牌的有效性则开放保护的资源。
服务端实现,验证令牌合法性后则开放用户授权的保护资源,很多时候,用户的资源是与权限对应的。令牌可能只包含了用户特定的授权凭据,准确的说,令牌对应用户授权时所赋予的一系列权限的集合。所以在这一步,除了校验令牌的合法性之外,服务端还需对该令牌是否拥有足够的权限执行被保护操作进行验证。
简单例举我想到的一些问题吧
1.请求授权码过程服务端最好启用授权域(scope)需要对授权的令牌的有效权限进行验证,以免泄露过多用户数据 ,启用state,用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验。
2.获得授权码重定向的地址,为了防止有攻击者伪造重定向地址骗取用户授权,服务提供方应对授权时的重定向地址进行验证或判断是不是同一个域,所以申请应用的时候应该有appkey,appsecret,redirect_uri基础配置参数。
3.确保授权码一次性与有效时间,令牌有效时间验证,改用HTTPS来加密,确保通信内容不被第三方窃取。
Refer:
http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
标签:blog http io ar os 使用 sp strong on
原文地址:http://www.cnblogs.com/Irving/p/4134629.html