OAuth2.0 鉴权 (微信公众平台、腾讯微博)

创建时间:
2014-02-20 13:42
最近更新:
2014-09-17 14:46

Tony Remark

本文是 Tony 阅读
http://www.cnblogs.com/shaohz2014/p/3635802.html
http://www.cnblogs.com/steven9801/p/3282493.html
时整理的笔记。

使用腾讯 API 的前提

  • 注册成为 "开发者",从而获得 appkey 与 appsecret。
  • 获取 accesstoken。Accesstoken 是第三方获得用户授权的凭证,是第三方访问 API 资源的票据。

获取 accesstoken 的两种方式

用户通过 Oauth2.0 授权第三方有两种方式:

  • Authorization code grant: 适用于 PC,无线客户端等需要和第三方 server 进行交互的应用场景。使用 Authorization Code 授权,第三方能够集中处理用户的授权请求和授权结果,适用于有 server 端的应用。Authorization Code 授权流程分为两步,首先获取 code,然后用 code 换取 accesstoken。
  • Implicit grant: 适用于没有 Server 端的客户端应用,由客户端发起授权请求,保存和处理 accesstoken。

两种方式在授权的时候有所区别:

  • Authorization code grant 方式请求的 URL 中传递的 response_type 参数的值为 code,服务提供者回调时会在 QueryString 中带上 code,之后凭 code 再请求 access_token。
  • Implicit grant 方式请求的 URL 中传递的 response_type 参数的值为 token,服务提供者回调时会在 QueryString 中带上 access_token,省了不少步骤。

获得 access_token 之后,两者调用 API 的方式是一致的。

微信公众平台 OAuth2.0 授权详细步骤

  1. 用户关注微信公众账号。
  2. 微信公众账号提供用户请求授权页面 URL。
  3. 用户点击授权页面 URL,将向服务器发起请求。
  4. 服务器询问用户是否同意授权给微信公众账号 (scope 为 snsapi_base 时无此步骤)。
  5. 用户同意 (scope 为 snsapi_base 时无此步骤)。
  6. 服务器将 CODE 通过回调传给微信公众账号。
  7. 微信公众账号获得 CODE。
  8. 微信公众账号通过 CODE 向服务器请求 Access Token。
  9. 服务器返回 Access Token 和 OpenID 给微信公众账号。
  10. 微信公众账号通过 Access Token 向服务器请求用户信息 (scope 为 snsapi_base 时无此步骤)。
  11. 服务器将用户信息回送给微信公众账号 (scope 为 snsapi_base 时无此步骤)。

开发者凭据

在 "微信公众平台后台 - 功能 - 高级功能 - 开发模式 - 开发者凭据" 页面中可以找到或重置:

  • AppId
  • AppSecret

配置 "授权回调页面域名"

授权回调页面域名:用户在网页授权页同意授权给公众号后,微信会将授权数据传给一个回调页面,回调页面需在此域名下,以确保安全可靠。

在 "微信公众平台后台 - 服务 - 我的服务 - OAuth2.0 网页授权" 页面,设置 "授权回调页面域名"。

授权回调域名配置规范为全域名并且不带 http,比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面
http://www.qq.com/music.html
http://www.qq.com/login.html
都可以进行 OAuth2.0 鉴权。但
http://pay.qq.com
http://music.qq.com
http://qq.com
无法进行 OAuth2.0 鉴权。

授权页面的请求格式

https://open.weixin.qq.com/connect/oauth2/authorize
?appid=APPID
&redirect_uri=REDIRECT_URI
&response_type=code
&scope=SCOPE
&state=STATE
#wechat_redirect
参数说明
参数 是否必须 说明
appid 公众号的唯一标识。即服务提供方为该应用分配的 AppKey。
redirect_uri 授权后回调的地址,必须和应用注册的地址一致。
response_type 授权类型,值固定为 "code"。
scope 应用授权作用域,snsapi_base: 不弹出授权页面,直接跳转,只能获取用户 openid;snsapi_userinfo: 弹出授权页面,可通过 openid 拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息。
state 用于保持请求和回调的状态,授权请求成功后原样带回给第三方。该参数用于防止 CSRF (跨站请求伪造攻击),强烈建议第三方带上该参数。开发者可以设置为任意参数值,建议设置为简单随机数 + session。
#wechat_redirect 直接在微信打开链接,可以不填此参数。做页面 302 重定向时候,必须带此参数。

示例

https://open.weixin.qq.com/connect/oauth2/authorize
?appid=wx8888888888888888
&redirect_uri=http://mascot.duapp.com/oauth2.php //回调地址:填写为刚才上传后的 oauth2.php 的文件地址。
&response_type=code
&scope=snsapi_userinfo //应用授权作用域:由于 snsapi_base 只能获取到 openid,意义不大,所以我们使用 snsapi_userinfo。
&state=1 //state 参数:随便一个数字,这里填 1。
#wechat_redirect

可以将上述 URL 封装在 HTML-a-tag 中,并作为微信发送,对方的微信收到后会呈现为可点击的链接,点击后会转到公众号授权页面,显示该公众号的公司信息、同意此应用获取你的个人信息复选框、取消/允许按钮。

如果勾选并单击允许按钮,将被重定向至 http://mascot.duapp.com/oauth2.php?code=00b788e3b42043c8459a57a8d8ab5d9f&state=1,此时应用可获得 code 与 state 参数值。

使用 code 换取 access_token 的请求格式

https://api.weixin.qq.com/sns/oauth2/access_token
?appid=APPID
&secret=SECRET
&code=CODE
&grant_type=authorization_code
参数说明
参数 是否必须 说明
appid 公众号的唯一标识。即服务提供方为该应用分配的 AppKey。
secret 公众号的 AppSecret。即服务提供方为该应用分配的 AppSecret。
code 填写上步获取的 code 参数的值。
grant_type 值固定为 "authorization_code"。

示例

https://api.weixin.qq.com/sns/oauth2/access_token
?appid=wx8888888888888888
&secret=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
&code=00b788e3b42043c8459a57a8d8ab5d9f
&grant_type=authorization_code

请求上述 URL 将返回以下 JSON,至此,成功的通过 code 换取到了 access_token,以及 refresh_token:

{
	"access_token": "OezXcEiiBSKSxW0eoylIeAsR0GmYd1awCffdHgb4fhS_KKf2CotGj2cBNUKQQvj-G0ZWEE5-uBjBz941EOPqDQy5sS_GCs2z40dnvU99Y5AI1bw2uqN--2jXoBLIM5d6L9RImvm8Vg8cBAiLpWA8Vw",
	"expires_in": 7200,
	"refresh_token": "OezXcEiiBSKSxW0eoylIeAsR0GmYd1awCffdHgb4fhS_KKf2CotGj2cBNUKQQvj-G0ZWEE5-uBjBz941EOPqDQy5sS_GCs2z40dnvU99Y5CZPAwZksiuz_6x_TfkLoXLU7kdKM2232WDXB3Msuzq1A",
	"openid": "oLVPpjqs9BhvzwPj5A-vTYAX3GLc",
	"scope": "snsapi_userinfo,"
}
JSON 格式解读
参数 描述
access_token 网页授权接口调用凭证,注意:此 access_token 与基础支持的 access_token 不同。
expires_in access_token 接口调用凭证超时时间,单位秒。
refresh_token 用户刷新 access_token。
openid 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的 OpenID。
scope 用户授权的作用域,使用逗号分隔。

注意:在任意浏览器中请求上述 URL 均可获得上述返回 JSON。所以,在 code 的有效期内,是可能被盗用的。

刷新 access_token

Oauth2 中,access_token 的有效期不是无限的,当第三方应用使用的 access_token 时间超过了其生命周期时,可以通过刷新机制来获取新的 access_token。

https://api.weixin.qq.com/sns/oauth2/refresh_token
?appid=APPID
&grant_type=refresh_token
&refresh_token=REFRESH_TOKEN
参数说明
参数 是否必须 说明
appid 公众号的唯一标识。即服务提供方为该应用分配的 AppKey。
grant_type 值固定为 "refresh_token"。
refresh_token 上次授权或者刷新时获取的 refresh_token。

示例

https://api.weixin.qq.com/sns/oauth2/refresh_token
?appid=wx8888888888888888
&grant_type=refresh_token
&refresh_token=OezXcEiiBSKSxW0eoylIeAsR0GmYd1awCffdHgb4fhS_KKf2CotGj2cBNUKQQvj-G0ZWEE5-uBjBz941EOPqDQy5sS_GCs2z40dnvU99Y5CZPAwZksiuz_6x_TfkLoXLU7kdKM2232WDXB3Msuzq1A

返回的数据可能类似于:

?access_token=ACCESS_TOKEN
&expires_in=60
&refresh_token=REFRESH_TOKEN
&name=NAME

accesstoken 过期时间:初级、高级及腾讯合作方应用,accesstoken 有效期均为三个月。
通过刷新机制可以延长 access_token 有效期,每次刷新延长的 access_token 有效期与授权时 access_token 的有效期一致,多次刷新可将 access_token 的有效期延长至一年。

使用 access_token 获取用户信息

https://api.weixin.qq.com/sns/userinfo
?access_token=ACCESS_TOKEN
&openid=OPENID
参数说明
参数 描述
access_token 网页授权接口调用凭证,注意:此 access_token 与基础支持的 access_token 不同。
openid 用户的唯一标识。

示例

https://api.weixin.qq.com/sns/userinfo
?access_token=OezXcEiiBSKSxW0eoylIeAsR0GmYd1awCffdHgb4fhS_KKf2CotGj2cBNUKQQvj-G0ZWEE5-uBjBz941EOPqDQy5sS_GCs2z40dnvU99Y5AI1bw2uqN--2jXoBLIM5d6L9RImvm8Vg8cBAiLpWA8Vw
&openid=oLVPpjqs9BhvzwPj5A-vTYAX3GLc

在任意浏览器中请求上述 URL 均返回以下 JSON

{
	"openid": "oLVPpjqs9BhvzwPj5A-vTYAX3GLc",
	"nickname": "方倍",
	"sex": 1,
	"language": "zh_CN",
	"city": "Shenzhen",
	"province": "Guangdong",
	"country": "CN",
	"headimgurl": "http://wx.qlogo.cn/mmopen/utpKYf69VAbCRDRlbUsPsdQN38DoibCkrU6SAMCSNx558eTaLVM8PyM6jlEGzOrH67hyZibIZPXu4BK1XNWzSXB3Cs4qpBBg18/0",
	"privilege": []
}
上述 JSON 参数解读
参数 描述
openid 用户的唯一标识。
nickname 用户昵称。
sex 用户的性别,值为 1 时是男性,值为 2 时是女性,值为 0 时是未知。
province 用户个人资料填写的省份。
city 普通用户个人资料填写的城市。
country 国家,如中国为 CN。
headimgurl 用户头像,最后一个数值代表正方形头像大小 (有 0、46、64、96、132 数值可选,0 代表 640*640 正方形头像),用户没有头像时该项为空。
privilege 用户特权信息,json 数组,如微信沃卡用户为 (chinaunicom)。

至此,在不输入我的账号及密码的情况下,微信公众账号近宝获得了我的个人信息,这些信息包括昵称、性别、国家、省份、城市、个人头像以及特权列表。一个完整的OAuth2认证就完成了。