Demand: login applet using micro channel, a rear end user obtain details (including openid, unionid) into the database, and generates a token
Sign in to get token applet
1. wx.login acquired by the code,
2.wx.getUserInfo get to the encrypted data encryptedData, and iv,
3. send data to the background in exchange for token
Applet code
var that = this;
wx.getSetting({
success(res) {
var status = res.authSetting['scope.userInfo']
if (status) {
wx.login({
success(res) {
if (res.code) {
var code = res.code;
wx.getUserInfo({
success(res) {
wx.showLoading({
title: '登陆中',
mask: true
});
that.login(code, res.encryptedData, res.iv)
}
})
}
}
})
}
}
})
/**
* 登录获取token
*/
function login(code, encrypteData, iv) {
var that = this
wx.showToast({
title: '正在登录...',
icon: 'loading',
duration: 5000
});
wx.request({
url: url,
method: 'get',
data: {
code: code,
encrypteData: encrypteData,
iv: iv
},
header: {
'Content-Type': 'application/json'
},
success: function(res) {
if (res.data.code == 0) {
that.globalData.token = res.data.data
wx.hideLoading()
} else
console.error(res);
},
fail: function() {
wx.showToast({
title: '网络错误!',
duration: 2000
})
},
complete: function() {
}
})
Server Registration
1. distal token request submitted by a micro channel server retrieves session_key,
2. session_key, iv decrypt the encrypted data to obtain the user information
3. To determine whether or not registered, written to the database
4. Generate token
Code
/**
* Notes:登录并注册
* @auther: xxf
* Date: 2019/9/29
* Time: 14:22
* @param Request $request
* @return \think\response\Json
*/
public function login(Request $request)
{
$code = $request->post('code');
$encryptedData = $this->request->post('encryptedData');
$iv = $this->request->post('iv');
$model = new User();
$res = $model->userLogin($code,$iv,$encryptedData);
return json($res);
}
public function userLogin($code,$iv,$encrypteData)
{
try {
$url = "https://api.weixin.qq.com/sns/jscode2session?appid=$this->appId&secret=$this->appSecret&js_code=$code&grant_type=authorization_code";
$tokenValue = $this->httpGet($url);
$data = $this->decryptData($this->appId,$tokenValue->session_key,$encrypteData,$iv);
$user = User::where('openid',$tokenValue->openid)->find();
if($user instanceof User) {
$user->lasttime = time();
$user->head = $data['avatarUrl'];
$user->save();
$mid = $user->id;
}else{
$userData = array([
'openid' => $data['openId'],
'name' => $data['nickName'],
'head' => $data['avatarUrl'],
'sex' => $data['gender'],
'address' => $data['country'].$data['province'].$data['city'],
'addtime' => time(),
'lasttime' => time(),
]);
$mid = $this->insertGetId($userData);
}
if ($mid)
{
$jwtToken = new Token();
$tokenData = array(
'mid' => $mid,
);
$token = $jwtToken->createToken($tokenData, 86400)['token'];
return ['data' => $token, 'code' => 0, 'msg' => 'success'];
} else
return ['data' => '', 'code' => 1, 'msg' => '异常'];
} catch (\Exception $e)
{
return ['data' => '', 'code' => 1, 'msg' => $e->getMessage()];
}
}
/**
* Notes:数据解密
* @auther: xxf
* Date: 2019/9/29
* Time: 15:44
* @param $appId
* @param $session_key
* @param $encryptedData
* @param $iv
* @return mixed|string
* @throws \Exception
*/
private function decryptData( $appId,$session_key,$encryptedData, $iv)
{
if (strlen($session_key) != 24 || strlen($iv) != 24) {
throw new \Exception("encodingAesKey或iv 非法");
}
$aesKey=base64_decode($session_key);
$aesIV=base64_decode($iv);
$aesCipher=base64_decode($encryptedData);
$result=openssl_decrypt( $aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
$dataObj=json_decode( $result );
$result = json_decode($result,true);
if( $dataObj == NULL )
throw new \Exception("解密失败");
if( $dataObj->watermark->appid != $appId )
throw new \Exception("解密失败");
return $result;
}
private function httpGet($url) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 500);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_URL, $url);
$res = curl_exec($curl);
curl_close($curl);
return json_decode($res);
}
Other service authentication token verification
When the applet subsequent requests, carrying token in the header
wx.request({
url: _api,
header: {
'content-type': 'application/json',
'Authorization': token
},
method: 'POST',
data: data,
success: function (res) {
if(res.statusCode == 401)
{
wx.showToast({
title: '未登录',
image: "/assets/icon/icon-warning.png",
});
}
success(res);
}
});
Background middleware code
public function handle($request, \Closure $next)
{
$token = $request->header('AUTHORIZATION');
$jwtToken = new Token();
$checkToken = $jwtToken->checkToken($token);
$data = (array)$checkToken['data']['data'];
$mid = $data['mid'] ?? 0 ;
$user = User::where('id',$mid)->find();
if($user instanceof User){
$request->user = $user;
return $next($request);
}else{
$res = [
'data' => '',
'code'=>1,
'msg'=>'未登录'
];
sendResponse($res, 401, 'Unauthorized');
}
}
About the token generation see my other blog