關於oauth2.0
OAuth 2.0授權框架支持第三方支持訪問有限的HTTP服務,通過在資源所有者和HTTP服務之間進行一個批准交互來代表資源者去訪問這些資源,或者通過允許第三方應用程序以自己的名義獲取訪問權限。
為了方便理解,可以想象OAuth2.0就是在用戶資源和第三方應用之間的一個中間層,它把資源和第三方應用隔開,使得第三方應用無法直接訪問資源,從而起到保護資源的作用。
為了訪問這種受保護的資源,第三方應用(客戶端)在訪問的時候需要提供憑證。即,需要告訴OAuth2.0你是誰你要做什么。
OAuth定義了四種角色:
- resource owner(資源所有者)
- resource server(資源服務器)
- client(客戶端):代表資源所有者並且經過所有者授權去訪問受保護的資源的應用程序
- authorization server(授權服務器):在成功驗證資源所有者並獲得授權后向客戶端發出訪問令牌
抽象的OAuth2.0流程如圖所示:
- (A) 客戶端向資源所有者請求其授權
- (B) 客戶端收到資源所有者的授權許可,這個授權許可是一個代表資源所有者授權的憑據
- (C) 客戶端向授權服務器請求訪問令牌,並出示授權許可
- (D) 授權服務器對客戶端身份進行認證,並校驗授權許可,如果都是有效的,則發放訪問令牌
- (E) 客戶端向資源服務器請求受保護的資源,並出示訪問令牌
- (F) 資源服務器校驗訪問令牌,如果令牌有效,則提供服務
聯想一下微信公眾平台開發,在微信公眾平台開發過程中當我們訪問某個頁面,頁面可能彈出一個提示框應用需要獲取我們的個人信息問是否允許,點確認其實就是授權第三方應用獲取我們在微信公眾平台的個人信息。這里微信網頁授權就是使用的OAuth2.0。
微信網頁授權實例
[微信公眾平台|開發文檔] http://mp.weixin.qq.com/wiki/home/。
實現步驟:
2 第二步:通過code換取網頁授權access_token
3 第三步:拉取用戶信息(需scope為 snsapi_userinfo)
第一步:用戶同意授權,獲取code
拼接如下地址,替換其中的參數, 在微信下打開
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
如果用戶同意授權,頁面將跳轉至 redirect_uri/?code=CODE&state=STATE。
獲取code代碼示例
/** * @explain * 獲取code,用於獲取openid和access_token * @remark * code只能使用一次,當獲取到之后code失效,再次獲取需要重新進入 * 不會彈出授權頁面,適用於關注公眾號后自定義菜單跳轉等,如果不關注,那么只能獲取openid **/ public function getCode() { if (isset($_GET["code"])) { return $_GET["code"]; } else { $str = "location: https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $this->appid . "&redirect_uri=" . $this->index_url . "&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect"; header($str); exit; } }
第二步:通過code換取網頁授權access_token
替換鏈接中的參數,在服務器端通過curl請求以下地址
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
返回數據如下
{ "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" }
代碼示例:
/** * @explain * 用於獲取access_token,返回的<span style="font-family: Arial, Helvetica, sans-serif;">$access_token_array中也包含有用戶的openid信息。</span> **/ public function getOpenId() { $access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" . $this->appid . "&secret=" . $this->appsecret . "&code=" . $this->code . "&grant_type=authorization_code"; $access_token_json = $this->https_request($access_token_url); $access_token_array = json_decode($access_token_json, TRUE); return $access_token_array; }
第三步:拉取用戶信息(需scope為 snsapi_userinfo)
http:GET(請使用https協議) https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
返回數據如下:
{ "openid":" OPENID", " nickname": NICKNAME, "sex":"1", "province":"PROVINCE" "city":"CITY", "country":"COUNTRY", "headimgurl": "http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46", "privilege":[ "PRIVILEGE1" "PRIVILEGE2" ], "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" }
代碼示例
/** * @explain * 獲取到用戶的openid之后可以判斷用戶是否有數據,可以直接跳過獲取access_token,也可以繼續獲取access_token **/ public function getUserInfo() { $userinfo_url = "https://api.weixin.qq.com/sns/userinfo?access_token=".$this->access_token['access_token'] ."&openid=" . $this->access_token['openid']."&lang=zh_CN"; $userinfo_json = $this->https_request($userinfo_url); $userinfo_array = json_decode($userinfo_json, TRUE); return $userinfo_array; }