微信小程序开发:登录那些事
小程序登录和平时自己APP的登录验证不一样。还有一个角色,那就是微信服务器。
根据微信官方的登录流程跟踪图,我们可以清楚地了解到登录小程序需要多少步骤。总结如下:
- 小程序启动,通过wx.login()获取代码
- 开发者服务器必须提供登录接口,参数为小程序获取的代码
- 之后收到验证码后,登录界面会调用微信接口验证验证码
- 得到验证结果。成功后可以获得session_key和openid
- 生成自定义key,将session_key和openid与自定义key关联起来
- 将自定义key发送回小程序
- 每次请求时带上key,后台就会根据密钥获取openid身份当前用户身份
首先,密码是微信给出的。如果随意生成代码来验证的话,肯定是无效的。仅微信提供的代码有效。代码发送到开发者自有服务后,询问微信:
朋友您好,我的代码有效还是无效?
微信会告诉你是否有效。如果有效的话,你还会得到一个用户ID,即openid,以及一个session_key,即会话的密钥。 session_key默认有效期为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前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。