微信小程序结合php后台实现登录授权机制详解
基本就是手机访问微信官方服务器获取到code用于标识用户,app服务器用该code和自己的appid和appsecrept来访问微信官方服务器,从而获得用户对于该app的唯一标识ID,即openid,然后app后台将此openid做成token,传给前台,供前台以后携带些token来证实自己身份。
微信小程序应用的用户登录授权机制相当复杂,官方给出了下面一张流程图来解释:
下面结合这张图来详细讲述下小程序的登录验证授权机制。
首先,小程序应用实现登录验证的前提是需要在微信开放平台注册一个开发者账号,申请到AppID 和 AppSecret。并申请开启“获取用户信息”的权限。
然后 ,在小程序中使用微信提供的 wx.login 接口获取用户的临时登录凭证 code。代码示例如下:
// 检查用户是否已经授权 wx.getSetting({ success: res => { if (res.authSetting['scope.userInfo']) { // 用户已经授权,可以直接调用 wx.getUserProfile 获取用户信息 wx.getUserProfile({ desc: '获取用户信息', success: res => { // 获取用户信息 const userInfo = res.userInfo; // 获取用户登录凭证 wx.login({ success: res => { // 获取用户登录凭证 const code = res.code; // 将 code 和 userInfo 发送到后台服务器进行处理 wx.request({ url: 'https://example.com/login.php', data: { code: code, userInfo: userInfo }, method: 'POST', success: function (res) { console.log(res.data); } }); } }) } }) } else { // 用户未授权,需要显示授权弹窗 wx.authorize({ scope: 'scope.userInfo', success: () => { // 用户完成授权,可以继续获取用户信息 wx.getUserProfile({ desc: '获取用户信息', success: res => { // 获取用户信息 const userInfo = res.userInfo; // 获取用户登录凭证 wx.login({ success: res => { // 获取用户登录凭证 const code = res.code; // 将 code 和 userInfo 发送到后台服务器进行处理 wx.request({ url: 'https://example.com/login.php', data: { code: code, userInfo: userInfo }, method: 'POST', success: function (res) { wx.setStorage({ key: "token", data: res.data.token }) console.log(res.data); } }); } }) } }) } }) } } })
接着,小程序前台应用将获取到的 code 发送给后台服务器进行登录验证。后台服务器需要使用微信提供的接口(例如 wx.login 和 wx.getUserInfo)通过 code 获取用户的唯一标识 OpenID 和会话密钥 session_key。然后将用户的 OpenID 和 session_key 存储到后台数据库中,并将一个自定义的 token 返回给小程序前端。php代码示例如下:
$appid = 'your_appid';
$appsecret = 'your_appsecret';
$code = $_POST['code'];
$url = "https://api.weixin.qq.com/sns/jscode2session?appid=$appid&secret=$appsecret&js_code=$code&grant_type=authorization_code"; $result = file_get_contents($url);
$data = json_decode($result, true);
$openid = $data['openid'];
$session_key = $data['session_key'];
// 存储到数据库中
$db = new mysqli('localhost', 'username', 'password', 'database');
$sql = "INSERT INTO `user`(`openid`, `session_key`) VALUES ('{$openid}', '{$session_key}')";
$result = $db->query($sql);
接下来,php根据openid和session_key再生成token,返还给前台小程序应用。
function generateToken($openid, $session_key) { $header = [ 'typ' => 'JWT', 'alg' => 'HS256' ]; $payload = [ 'openid' => $openid, 'iat' => time(), 'exp' => time() + 3600 ]; $secret = 'my_secret_key'; // 生成 JWT Token $base64UrlHeader = base64UrlEncode(json_encode($header)); $base64UrlPayload = base64UrlEncode(json_encode($payload)); $signature = hash_hmac('sha256', $base64UrlHeader . '.' . $base64UrlPayload, $secret, true); $base64UrlSignature = base64UrlEncode($signature); $token = $base64UrlHeader . '.' . $base64UrlPayload . '.' . $base64UrlSignature; return $token; } function base64UrlEncode($data) { $urlSafeData = strtr(base64_encode($data), '+/', '-_'); return rtrim($urlSafeData, '='); } $token = generateToken($openid, $session_key); echo json_encode(['token' => $token]);
前台小程序应用接收到后台返回的token后,将其存储在小程序的本地缓存中,以后每次用户打开小程序时,我们可以从本地缓存中读取token并发送给后台进行验证。
如下示例:
// 获取本地缓存中的token const token = wx.getStorageSync('token'); // 如果本地缓存中存在token,则向后台发送请求获取用户信息 if (token) { wx.request({ url: 'https://example.com/userinfo', header: { 'Authorization': `Bearer ${token}` }, success: res => { // 处理响应结果 console.log(res.data); } }); } else { // 如果本地缓存中不存在token,则说明用户还未登录,需要重新登录获取token wx.login({ success: res => { // 向后台发送code,获取token wx.request({ url: 'https://example.com/login', data: { code: res.code }, success: res => { // 将后台返回的token存储到本地缓存中 wx.setStorageSync('token', res.data.token); // 向后台发送请求获取用户信息 wx.request({ url: 'https://example.com/userinfo', header: { 'Authorization': `Bearer ${res.data.token}` }, success: res => { // 处理响应结果 console.log(res.data); } }); } }); } }); }
php后台获取到前台发来的请求及token后,就直接根据token来验证用户,如下代码所示:
<?php use \Firebase\JWT\JWT; // JWT secret key $secret_key = "your_secret_key"; // Token received from front-end $secret_key和$token如存在数据库中,则从数据库中获取 $token = "token_received_from_front_end"; try { // Decode token and get the payload $payload = JWT::decode($token, $secret_key, array('HS256')); // You can now access the token payload data $user_id = $payload->user_id; $username = $payload->username; // ... // Token is valid echo "Token is valid!"; } catch (Exception $e) { // Token is invalid echo "Token is invalid: " . $e->getMessage(); } ?>
如此,则完成整个登录验证机制的实现。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端