主要是在项目中遇到网页受权登陆这个需求,就对此作些总结记录。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;
}
}
代码结合实现思路,大体思想清楚就好实现了,但愿对你们有帮助(代码写的烂,将就看吧)。微信