微信受權登陸(PHP)

微信受權登陸(PHP)

主要是在項目中遇到網頁受權登陸這個需求,就對此作些總結記錄。php

OAuth2.0受權
OAuth是一個開放協議,容許用戶讓第三方應用以安全且標準的方式獲取該用戶在某一網站、移動或桌面應用上存儲的我的信息,而無需將用戶名和密碼提供給第三方應用。常見微信、QQ登陸,省去管理帳戶的麻煩,也不會形成用戶的流失。html

打開微信的官方文檔,會看到網頁受權一些說明。(有點摸不着頭腦,主要是當時沒能關聯起來,微信文檔每次看都那麼鬱悶!!!)數據庫

來了解下受權的模式,官方說的詳細(這得仔細閱讀下):
關於網頁受權的兩種scope的區別說明
一、以snsapi_base爲scope發起的網頁受權,是用來獲取進入頁面的用戶的openid的,而且是靜默受權並自動跳轉到回調頁的。用戶感知的就是直接進入了回調頁(每每是業務頁面)
二、以snsapi_userinfo爲scope發起的網頁受權,是用來獲取用戶的基本信息的。但這種受權須要用戶手動贊成,而且因爲用戶贊成過,因此無須關注,就可在受權後獲取該用戶的基本信息。
三、用戶管理類接口中的「獲取用戶基本信息接口」,是在用戶和公衆號產生消息交互或關注後事件推送後,才能根據用戶OpenID來獲取用戶基本信息。這個接口,包括其餘微信接口,都是須要該用戶(即openid)關注了公衆號後,才能調用成功的。json

實現思路

 

enter description here

101637543016285

 

  1. 在微信公衆號中設定網頁受權域名;
  2. 用戶打開登陸頁,進入網頁受權頁面url;
  3. 微信詢問用戶是否贊成受權給微信公衆號;(snsapi_base 靜默受權無此步驟,而且此模式snsapi_userinfo需關注微信公衆號)
  4. 用戶贊成受權(snsapi_base靜默受權直接默認贊成)
  5. 回調code,帶code參數請求微信,換取網頁受權access_token(此步獲取openid,微信用戶的惟一標識)
  6. 經過【獲取用戶基本信息】接口,參數access_token(和上面的不一樣,普通的access_token)和openid,判斷是否綁定微信公衆號,未綁定,跳轉綁定頁。(此步驟snsapi_base無需,固然這個步驟能夠去掉,視狀況而定,像我項目就有這要求,唉)
  7. 將openid帶入登陸頁,商戶服務器檢測當前openid是否存在數據庫用戶記錄中
  8. 不存在openid記錄,登陸用戶,商戶服務器將openid存入用戶表中;(存在openid記錄跳過此步驟)
  9. openid記錄存在,則拉取用戶信息,存入會話,完成登陸;

以上是本人實際項目中的作法,除此以外咱們的接口作了簽名驗證,有必定安全性。僅供參考,總以爲有更好的思路,但願你們指出。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;
    }

}

代碼結合實現思路,大體思想清楚就好實現了,但願對你們有幫助(代碼寫的爛,將就看吧)。微信

—— 路漫漫其修遠兮 吾將上下而求索
相關文章
相關標籤/搜索