您现在的位置是:主页>前端技术>小程序Token认证介绍 网站首页

小程序Token认证介绍


网络通信离不开用户身份校验,以下是几种常见的认证机制

1:cookie auth: 浏览器Cookie存放用户信息,每次请求会默认自动带上Cookie信息,后端服务通过解析Cookie还原用户身份,不同域名无法共享cookie信息,可设置过期时间。

2:token auth:  通过服务器特定接口返回一个能够识别用户身份字符,每次请求的时候加到请求信息里面用于校验用户身份,json web token 是目前最流行的跨域认证解决方案,根据策略可决定是否过期。


以下图片来自后文参考链接

其它的就不介绍了,小程序本身是不支持cookie此处主要讲解小程序token校验的例子。


token生成流程如下:

1:调用 wx.login 获取登录凭证(code)。

2: 调用后台接口通过凭证进而换取用户登录态信息,包括用户的唯一标识(openid)

3:过微信唯一标识openid映射用户id,通过相关规则使用用户id或者openidtoken信息返回给小程序客户端。

4:把token存入storage每次请求接口时候带上token信息,用以识别用户身份。


使用Signature 防止数据篡改,生成流程如下

1:首先需要指定密钥(secret),和后台服务器协商一致,不能泄露到请求里。

2:通过算法可自己定义,需要包含(token+secret+timestamp+重要数据)。本例中为:

   sha1.hex_sha1(token + timestamp + nonceStr + secret).toLowerCase()

校验流程:后端服务器通过请求体获取到token,timestamp,nonceStr等信息,使用协商的secret通过相同的加密方式生产对应的sign,再和请求体里面携带的sign比较相同则校验通过.在加密方式和secret没有泄露的情况下,可以确认请求是由客户端真实发起的。


小程序端关键步骤如下:

function trySettingToken() {
  var app = getApp();
  let promise = new Promise(function (resolve, reject) {
    var token = wx.getStorageSync('token');
    if (token) {
      resolve();
      return;
    }
    wx.login({
      success: function (res) {
        //登录成功 
        if (res.code) {
          // 这里是用户的授权信息每次都不一样 
          var code = res.code;
          var userInfo = app.globalData.userInfo;
          Login(code, userInfo).then(resolve);
        }
      }, fail: function (res) {
        reject(res);
      }
    })
  });
  return promise;
}
function Login(code, userInfo) {
  var url = getLoginUrl(code, userInfo);
  let promise = new Promise(function (resolve, reject) {
    return https.get(url, function (res) {
      var token = res.token;
      wx.setStorageSync('token', token);
      resolve(res);
    }, function (res) {
    
      // 在这里你要考虑到用户登录失败的情况 
      reject(res);
    }, false)
  });
  return promise;
}
function rewriteUrl(url) {
  var token = getToken();
  var timestamp = time.getCurrentTimestamp();
  var nonceStr = random.getRandomNum(100000, 999999);
  var sign = sha1.hex_sha1(token + timestamp + nonceStr + Secret).toLowerCase();
  if (url.indexOf("?") > -1) {
    url += `&token=${token}&nonceStr=${nonceStr}&sign=${sign}×tamp=${timestamp}`;
  } else {
    url += `?token=${token}&nonceStr=${nonceStr}&sign=${sign}×tamp=${timestamp}`;
  }
  return url;
}

后端校验关键步骤如下:


string url = $"https://api.weixin.qq.com/sns/jscode2session?appid={AppID}&secret={AppSecret}&js_code={code}&grant_type=authorization_code";
try
{
    string rtn = HttpsUtil.Get(url, string.Empty);
    WechatAuthorizationInfo info = JsonUtil.ToEntity(rtn);
    if (!string.IsNullOrEmpty(info.openid))
    {
        if (user != null && !string.IsNullOrEmpty(user.NickName))
        {
            //添加账号信息
            user.OpenId = info.openid;
            new UserService().Save(user);
        }
        string token = SignHelper.SignHash(info.openid);
        return Json(new { token = token, expires_in = info.expires_in }, JsonRequestBehavior.AllowGet);
    }
    else
    {
        return Json(rtn, JsonRequestBehavior.AllowGet);
        //return Json(ReturnInfoFactory.Create(false, ReturnCode.微信返回异常), JsonRequestBehavior.AllowGet);
    }
}
catch
{
    return Json(ReturnInfoFactory.Create(false, ReturnCode.服务器异常), JsonRequestBehavior.AllowGet);
}
public static bool CheckSign(string token, string timestamp, string nonceStr, string sign)
{
    return sign == Sha1Util.EncryptToSHA1(HttpUtility.UrlEncode(token) + timestamp.ToString() + nonceStr + SignSecret).ToLower();
}


参考资料:


基于Token的WEB后台认证机制


Top