Code前端首页关于Code前端联系我们

微信小程序开发:登录那些事

terry 2年前 (2023-09-23) 阅读数 70 #移动小程序

小程序登录和平时自己APP的登录验证不一样。还有一个角色,那就是微信服务器。 微信小程序开发:登录那些事

根据微信官方的登录流程跟踪图,我们可以清楚地了解到登录小程序需要多少步骤。总结如下:

  • 小程序启动,通过wx.login()获取代码
  • 开发者服务器必须提供登录接口,参数为小程序获取的代码
  • 之后收到验证码后,登录界面会调用微信接口验证验证码
  • 得到验证结果。成功后可以获得session_key和openid
  • 生成自定义key,将session_key和openid与自定义key关联起来
  • 将自定义key发送回小程序
  • 每次请求时带上key,后台就会根据密钥获取openid身份当前用户身份

首先,密码是微信给出的。如果随意生成代码来验证的话,肯定是无效的。仅微信提供的代码有效。代码发送到开发者自有服务后,询问微信:

朋友您好,我的代码有效还是无效?

微信会告诉你是否有效。如果有效的话,你还会得到一个用户ID,即openid,以及一个session_key,即会话的密钥。 session_key默认有效期为2小时。当用户使用完小程序后,会自动刷新。这是微信维护的。

注:

  1. 会话密钥会话密钥是用户数据加密签名的密钥。为了应用程序自身的数据安全,开发者服务器不应该向小程序提供会话密钥,也不应该向外界提供该密钥
  2. 临时凭证代码只能使用一次

所以我们需要为session_key创建一个别名。只有我们知道该别名与哪个用户关联。唯一需要做的工作就在这里。

我推荐两种方式进行链接:

第一种:随机生成一个key,链接openid并保存到redis。当请求返回key时,openid直接从redis中获取当前用户信息。 ,这其实就是说我们自己维护session信息

第二种:使用JWT生成token,将openid绑定到token上,将token返回给小程序,请求的时候带上token,然后解析token获取用户信息。

下面我们以第二种方式进行讲解,贴上部分代码:

在小程序中,在app.js中的onLaunch方法中添加代码获取方法,调用后端登录接口获取token :

wx.login({
      success: function (res) {
        var code = res.code;
        if (code) {
          console.log('app启动获取用户登录凭证:' + code);
          let params = { "code": code };
          let result = config.requestHttp(config.url.userLogin, 'POST', params)
          result.then(res => {
            let data = res.data
            if (data.code == 200) {
              wx.setStorageSync("login_token", data.data.token);
            }
          }).catch(err => {
            console.log(err)
          });
        } else {
          console.log('获取用户登录态失败:' + res.errMsg);
        }
      }
})
复制代码

userLogin接口根据小程序代码调用微信接口认证:

// 小程序获取SessionKey接口地址
String loginUrl = "https://api.weixin.qq.com/sns/jscode2session";
String url = loginUrl + "?appid=%s&secret=%s&grant_type=%s&js_code=%s";
url = String.format(url, appid, appSecret, grantType, param.getCode());
String result = restTemplate.getForObject(url, String.class);
Map<String, Object> map = JsonUtils.toBean(Map.class, result);
// 请求成功
if (map.containsKey("session_key")) {
	String openid = map.get("openid").toString();
    // 第一次保存到用户表,生成JWT TOKEN返回
}
复制代码

小程序必须将wx.request()封装在全局方法中。所有与后台的交互都使用该方法来调用接口。在这个方法中我们可以设置登录后获取的token。这样,对于每个请求,token都会放在请求头中,我们可以在网关中获取这个token进行解析和验证。

//请求封装
function requestHttp(url, method, data) {
  //请求头设置
  var header = {
    Authorization: wx.getStorageSync("login_token")
  }
  return new Promise((resolve, reject) => {
    wx.request({
      url: config.home_config + url,
      data: data,
      header: header,
      method: method,
      success: (res => {
        if (res.data.code === 200) {
          resolve(res)
        } else {
          reject(res)
        }
      }),
      fail: (res => {
        reject(res)
      })
    })
  })
}
复制代码

Zuul中的验证:

  RequestContext ctx = RequestContext.getCurrentContext();
  HttpServletRequest request = ctx.getRequest();
  String token = request.getHeader("Authorization");
  if (StringUtils.isBlank(token)) {
    		ctx.setSendZuulResponse(false);
            ctx.set("isSuccess", false);
            ctx.setResponseBody(JsonUtils.toJson(Response.fail("非法请求【缺少Authorization】", ResponseCode.NO_AUTH_CODE)));
            ctx.getResponse().setContentType("application/json; charset=utf-8");
            return null;
  }
    
  // 验证Token是否有效
  JWTResult jwResult = JWTUtils.checkToken(token);
  if (!jwResult.isStatus()) {
    		ctx.setSendZuulResponse(false);
            ctx.set("isSuccess", false);
            ctx.setResponseBody(JsonUtils.toJson(Response.fail(jwResult.getMsg(), jwResult.getCode())));
            ctx.getResponse().setContentType("application/json; charset=utf-8");
            return null;
   }
   ctx.addZuulRequestHeader("loginUserId", jwResult.getUid());
   return null;
复制代码

认证成功后,将用户ID设置在请求头中,并传递给后端服务使用。

使用 JWT 时的一个问题是令牌过期。这里的过期时间设置为2小时。一般情况下,用户打开小程序时,连续使用时间不能超过2小时。登录逻辑在应用程序中。是用js完成的。只要下次输入token,就会再次应用。然而,这也可以调整,例如稍微长一些。

要点就是用户认证转移到微信上。只要微信告诉我们认证成功,我们就可以自己接管会话信息了。

作者:袁天地
链接:https://juejin.im/post/5c335a4ee51d45527201668f
来源:掘金
版权归作者所有。商业转载请联系作者获得许可。非商业转载请注明出处。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门