微信小程序全栈认证:基于 Token 的授权流设计与实现(WXML/WXSS/JS/PHP/SQL/JAVA)

2026-04-02 332 2  当前有 9 人在读此篇文章


在小程序开发中,建立一套安全且高效的身份认证体系是所有业务逻辑的基石。本文将深度解析一套成熟的“前端凭证获取 + 后端身份映射 + 令牌(Token)持久化”的全栈方案。

一、 系统架构与配置分离

为了保证代码的可维护性,首先需实现全局配置的解耦。在 config.js 中定义核心参数,避免硬编码:

// config.js - 全局环境配置
var DOMAIN = "api.your-domain.com"; // 生产环境 API 域名
var PAGECOUNT = '10';               // 分页步长

export default {
  getDomain: DOMAIN,
  getPageCount: PAGECOUNT,
  // 屏蔽具体业务版本号与私有配置
}

二、 客户端层:身份凭证获取流

小程序端的认证逻辑集中于 Auth.js。其核心是通过 Promise 封装异步调用,处理微信原生的 code 获取与用户信息上报。

1. 临时授权码(js_code)获取

wx.login 是认证的起点,获取到的 code 是后续换取用户唯一标识(OpenID)的必要凭证。

// Auth.js - 封装静默登录
Auth.wxLogin = function() {
    return new Promise(function (resolve, reject) {
        wx.login({
            success: function (res) {               
                let args = {};
                args.js_code = res.code; // 获取临时凭证                                
                resolve(args);                
            },
            fail: function (err) {
                reject(err);
            }
        });
    })
}

2. 用户上下文获取与上报

利用 wx.getUserProfile 获取非敏感元数据(昵称、头像),并触发后端认证接口。

// Auth.js - 处理用户显式授权逻辑
Auth.agreeGetUser = function(e, wxLoginInfo, authFlag) {
    return new Promise(function(resolve, reject) {
        let args = { js_code: wxLoginInfo.js_code };
        wx.getUserProfile({
            lang: 'zh_CN',
            desc: '用于完善会员资料',
            success: (res) => {
                let userInfo = res.userInfo;
                args.avatarUrl = userInfo.avatarUrl;
                args.nickname = userInfo.nickName;
                
                // 调用后端 API 执行身份交换
                var url = Api.getOpenidUrl();  
                var postOpenidRequest = wxRequest.postRequest(url, args);
                postOpenidRequest.then(response => {
                    if (response.data.status == '200') {
                        // 登录成功,执行状态持久化
                        resolve(response.data);
                    }
                })
            }
        });
    });
}

三、 服务端层:身份交换与账号映射逻辑

后端通过 REST API 接收客户端上报的 js_code,通过微信官方接口 jscode2session 完成从“微信用户”到“系统会员”的转换。

1. 路由注册与环境初始化

后端需确保跨域安全与环境兼容性,尤其针对 PHP 8.0+ 的 Session 策略进行防御性处理。

// User_Controller.php - REST 接口注册
public function register_routes() {
    register_rest_route($this->namespace, '/' . $this->module . '/login2', [
        'methods'  => 'POST',
        'callback' => [$this, 'user_login2'],
        'permission_callback' => '__return_true', // 允许公开访问鉴权接口
    ]);
}

2. 身份映射与 Token 签发

这是鉴权逻辑的核心。后端在获取 openid 后,需执行“存在即更新,不存在即创建”的幂等操作。

// User_Controller.php - 核心登录处理逻辑
public function user_login2($request) {
    $code = $this->param_value($request, 'code', '');
    $nickname = $this->param_value($request, 'nickName', '');

    // 1. 请求微信服务器换取 OpenID
    $params = [
        'appid'  => $app_id,     // 后端安全存储
        'secret' => $app_secret, // 后端安全存储
        'js_code' => $code,
        'grant_type' => 'authorization_code'
    ];
    $result = wp_remote_get(add_query_arg($params, 'https://api.weixin.qq.com/sns/jscode2session'));
    $wx_session = json_decode($result['body'], true);
    $openid = $wx_session['openid'] ?? '';

    // 2. 账号映射逻辑
    $user = get_user_by('login', $openid);
    if ($user) {
        $user_id = $user->ID;
        wp_update_user(['ID' => $user_id, 'display_name' => $nickname]);
    } else {
        $user_id = wp_insert_user([
            'user_login' => $openid, // 唯一标识作为用户名
            'role' => 'subscriber',
            'user_pass' => wp_generate_password(16, false),
        ]);
    }

    // 3. 生成并持久化业务 Token
    $token = md5(uniqid($openid, true));
    update_user_meta($user_id, 'custom_auth_token', $token);

    return $this->make_success([
        "nickname" => $nickname,
        "token" => $token, // 返回给前端的唯一授权令牌
    ]);
}

四、 业务授权流:基于 Token 的权限校验

在完成认证后,后续所有的业务请求(如点赞、收藏)均需携带 token 进行状态识别。

流程 逻辑实现 核心代码引用
客户端携带 从本地缓存读取并放入请求 Payload wx.getStorageSync('token')
服务端识别 通过 Meta 检索反查用户 ID get_user_id_by_token($token)
数据操作 校验通过后执行数据库事务 $wpdb->insert(...)
// User_Controller.php - 点赞业务权限校验
public function user_like($request) {
    global $wpdb;
    $token = $this->param_value($request, 'token', '');

    // 校验 Token 有效性,获取 UserID
    $user_id = $wpdb->get_var($wpdb->prepare(
        "SELECT user_id FROM $wpdb->usermeta WHERE meta_key='custom_auth_token' AND meta_value=%s LIMIT 1",
        $token
    ));

    if (!$user_id) {
        return $this->make_error('Invalid Token');
    }
    
    // 执行业务逻辑...
}

五、 总结与安全建议

本方案实现了 Stateless(无状态) 的会话管理模式,其优势在于:

  1. 解耦性:小程序前端不涉及任何敏感密钥(Secret),仅通过 code 与服务端通信。

  2. 持久化:利用 wx.setStorageSync 与服务端 user_meta 的映射,实现了用户在跨会话(Session)后的状态自动找回。

  3. 安全性:业务流程中使用随机 token 代替 openid 传输,显著降低了用户唯一标识被嗅探的风险。

Jinming

95后典型金牛座,强迫症。

相关推荐

使用手册

1.客户端配置: 将匹配浏览器的驱动覆盖到此目录 win平台 点击 此文件启动客户端 如授权过期 需要编辑sy ...

2 条评论

  1. 8mg

    看不懂,但是感觉很厉害👍🏻

发表评论

小程序 小程序
小程序