主要是在項目中遇到網頁受權登陸這個需求,就對此作些總結記錄。php
OAuth2.0受權
OAuth是一個開放協議,容許用戶讓第三方應用以安全且標準的方式獲取該用戶在某一網站、移動或桌面應用上存儲的我的信息,而無需將用戶名和密碼提供給第三方應用。常見微信、QQ登陸,省去管理帳戶的麻煩,也不會形成用戶的流失。html
打開微信的官方文檔,會看到網頁受權一些說明。(有點摸不着頭腦,主要是當時沒能關聯起來,微信文檔每次看都那麼鬱悶!!!)數據庫
來了解下受權的模式,官方說的詳細(這得仔細閱讀下):
關於網頁受權的兩種scope的區別說明
一、以snsapi_base爲scope發起的網頁受權,是用來獲取進入頁面的用戶的openid的,而且是靜默受權並自動跳轉到回調頁的。用戶感知的就是直接進入了回調頁(每每是業務頁面)
二、以snsapi_userinfo爲scope發起的網頁受權,是用來獲取用戶的基本信息的。但這種受權須要用戶手動贊成,而且因爲用戶贊成過,因此無須關注,就可在受權後獲取該用戶的基本信息。
三、用戶管理類接口中的「獲取用戶基本信息接口」,是在用戶和公衆號產生消息交互或關注後事件推送後,才能根據用戶OpenID來獲取用戶基本信息。這個接口,包括其餘微信接口,都是須要該用戶(即openid)關注了公衆號後,才能調用成功的。json
以上是本人實際項目中的作法,除此以外咱們的接口作了簽名驗證,有必定安全性。僅供參考,總以爲有更好的思路,但願你們指出。api
話很少說,貼出實現邏輯代碼:
商戶端登陸安全
public function actionLogin() {
session_start();
$_SESSION['openid'] = empty( $_SESSION['openid'] ) ? $_GET['openid'] : $_SESSION['openid'];
if(!$_GET['openid']){
$this->apiget('WeixinServer/ScopeRedirectUriAppid',array('sign'=>$this->sign,'sourcetype'=>7,'data' => ''));
header("Location:".Yii::app()->params['apipath'].'/WeixinServer/ScopeRedirectUriAppid?sign='.$this->sign.'&sourcetype=7' );
exit;
}
if($_SESSION['openid']){
//判斷綁定公衆號
$jssdk = new JSSDK();
$access_token = $jssdk->getAccessToken();
$url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={$access_token}&openid={$_SESSION['openid']}&lang=zh_CN";
$UserInfo = json_decode($this->dogetCurl($url),1);
if( empty($UserInfo['subscribe']) ){
//跳轉關注頁
header("Location:https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzA3Mzg2MjMyNw==&scene=124#wechat_redirect" );
die;
}
//微信登陸
$WeixinLogin = $this->apiget('WeixinServer/WeixinLogin', array('sign'=>$this->sign,'sourcetype'=>7,'openid'=>$_SESSION['openid']));
if( $WeixinLogin['error']==1){
return $this->render($this->act);
}
$this->WeinxinLogin($WeixinLogin);
die;
}
$this->render($this->act);
}
##微信受權成功 寫入session,跳轉首頁
public function WeinxinLogin( $data=array() ){
$_SESSION['user'] = $data['data'];
$this->redirect('/index/index');
}
##curl請求
public function apiget($path, $param=array()){
$url = Yii::app()->params['apipath'].$path;
$curl = curl_init();
curl_setopt($curl, CURLOPT_USERAGENT, '3'); //User-Agent
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $param);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$return = curl_exec($curl);
curl_close($curl);
$j = json_decode($return, 1);
return $return;
}
WeixinServer 處理微信受權服務器
<?php
class WeixinServerController extends Controller {
public function __construct() {
//todo 驗證簽名
}
public function error($msg){
header("Content-type: application/json");
$o['time'] = "".time();
$o['error'] = '1';
$o['errorMsg'] = $msg;
echo json_encode($o);die;
}
public function Login($user=array()){
//todo 獲取用戶信息
}
##=====================================微信受權========================================##
##微信受權登陸
public function actionWeixinLogin(){
if( empty($_POST['openid']) ) $this->error('openid爲空');
//todo 經過openid查詢用戶
$user = DB::get_one("SELECT * FROM {{user}} WHERE openid='{$_POST['openid']}' ");
if( !$user )$this->error('openid不存在');
$userinfo = $this->Login($user['uid']);
$this->out($userinfo);
}
##微信受權 獲取code
public function actionScopeRedirectUriAppid( ){
$APPID = "XXXXXXXXXXXX";
$REDIRECT_URI= 'http://'.$_SERVER['HTTP_HOST'].'/WeixinServer/WeixinOpenidCallback';
$scope='snsapi_base'; //手動受權snsapi_userinfo 靜默受權snsapi_base
$url='https://open.weixin.qq.com/connect/oauth2/authorize?appid='.$APPID.'&redirect_uri='.urlencode($REDIRECT_URI).'&response_type=code&scope='.$scope.'&state=scene#wechat_redirect';
header("Location:{$url}" );
}
##微信回調,獲取openid
public function actionWeixinOpenidCallback(){
if( $code= Yii::app()->request->getParam('code') ){
$APPID = "XXXXXXXXXXXX";
$SECRET = "XXXXXXXXXXXX";
$url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$APPID}&secret={$SECRET}&code={$code}&grant_type=authorization_code";
$UserOpenidArr = json_decode($this->dogetCurl($url),1);
if( empty($UserOpenidArr ['openid']) ) {
print_r( $UserOpenidArr );
die();
}
header("Location:http://XXXXXXXX/index/login?openid={$UserOpenidArr ['openid']}" );
}else{
die("微信受權失敗");
}
}
public function dogetCurl( $url ='' ) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt ( $ch, CURLOPT_HTTPHEADER, array( 'Connection: Keep-Alive', 'Keep-Alive: 300' ));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
curl_close ( $ch );
return $data;
}
}
代碼結合實現思路,大體思想清楚就好實現了,但願對你們有幫助(代碼寫的爛,將就看吧)。微信