生活随笔
收集整理的這篇文章主要介紹了
微信小程序中用户登录和登录态维护
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
微信小程序和以前的web項(xiàng)目不同,他是前后端分離的應(yīng)用,之前我們的傳統(tǒng)登錄有web服務(wù)器提供Session維護(hù), 后端在返回結(jié)果給前端web項(xiàng)目時(shí),帶上cookie,且以cookie值為key存儲用戶信息到session中,前端web項(xiàng)目在再以后端返回的結(jié)果中,得到相應(yīng)cookie的值,再一次以同樣的方式將cookie值返回給前端瀏覽器客戶端,這樣,后面每次瀏覽器客戶端請求時(shí)都會(huì)帶上cookie。微信小程序中沒有cooike,那么接下來我們來看下小程序如何登錄,以及如何維護(hù)微信小程序的登錄態(tài)(Session)。
官方登錄流程
直接引用官方的登錄文檔,我們的登錄維護(hù)都是按照這個(gè)文檔進(jìn)行的開發(fā),登錄流程圖如下圖所示:
1、在小程序中獲取微信用戶的登錄憑證(code)
小程序的登錄直接使用官方api接口wx.login(),從微信的官方服務(wù)器換取接口憑證code。
然后在小程序的app.js和后臺進(jìn)行交互,將code發(fā)給自己的后臺服務(wù)器進(jìn)行登錄換取token。
// 登錄
wx.login({
success: res => {
var that = this;
// 發(fā)送 res.code 到后臺換取 openId, sessionKey, unionId
console.log(res.code);
wx.setStorage({ //緩存code
key: "code",
data: res.code
})
console.log("code:" + res.code)
this.globalData.code = res.code;
var that = this;
var token = wx.getStorageSync('token') //同步取 token
console.log(token);
wx.request({
url: "http://10.5.5.118:8081/api/wechat/login",
header: {
'Authorization': token,
"Content-Type": "application/x-www-form-urlencoded" //POST的header必須是
},
method: "POST",
data: {
appType: "doctor",
code: res.code
},
success: function (res) {}
2、獲取用戶的openid和session_key
通過小程序請求的code,我們后臺再次請求微信的服務(wù)器獲取微信用戶的信息,也就是openid和session_key。
try {// url 地址微信規(guī)定只能這樣拼接String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + wechatConfig.getAppid() + "&secret="+ wechatConfig.getSecret() + "&js_code=" + code + "&grant_type=authorization_code";logger.info("發(fā)送獲取openid請求url:" + url);String result = httpApiService.doPost(url);logger.info("請求結(jié)果:" + result);ObjectMapper objectMapper = new ObjectMapper();// json 轉(zhuǎn)對象return objectMapper.readValue(result, WeChatResponse.class);} catch (Exception e) {logger.info("獲取openid失敗" + e);e.printStackTrace();throw new ServiceException("獲openid失敗", CustomErrorCode.INVALID_OPENID);}
請求地址:
https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
這里微信有一個(gè)規(guī)定,參數(shù)值只能拼接在后面,不能通過HttpClient的map參數(shù)放上去,需要注意一下。
通過這個(gè)接口的調(diào)用,可以拿到用戶openid,和session_key,現(xiàn)在當(dāng)前登錄的賬戶就在微信的服務(wù)器中產(chǎn)生了登錄態(tài)。
但是微信的官方文檔提示開發(fā)者,為了安全起見,需要第三方服務(wù)器自己定義一個(gè)登陸態(tài),并且把如何定義session的規(guī)則告訴了。
我們拿到了openid和session_key,將用戶的openid存入數(shù)據(jù)庫,通過加密算法把openid和session_key加密生成3rd_session:
// 3、獲取自定義登陸態(tài)生成token,由openid和session_key生key=rd_session,value=openidString rd_session = UUIDUtils.get16UUID();redisTemplate.opsForValue().set(rd_session, openid);
將3rd_session作為key,openid作為value存入redis,這里的3rd_session就是token,為了用戶的操作提供認(rèn)證,在用戶登陸成功時(shí),在header中攜帶token返回給用戶客戶端,用戶沒帶token請求,或者是token失效,都會(huì)請求失敗。
使用攔截器處理用戶的token認(rèn)證,將http請求中帶的認(rèn)證信息和redis的對比,如果存在沒失效,直接授權(quán)用戶請求,失效則攔截用戶的請求。
/*** 前置處理器* @param request* @param response* @param handler* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String token = request.getHeader("Authorization");logger.info("RequestURI:" + request.getRequestURI());String url = request.getRequestURI();logger.info("url: " + url);// 注冊不做攔截for (String urlConfig : config.getLoginConfigs()) {if (StringUtils.contains(url, urlConfig)) {logger.info("登陸非攔截地址" + url);// 清除上次登陸的tokenif (StringUtils.isNotEmpty(token)) {logger.info("清除上次登陸的token:" + token);redisTemplate.delete(token);}return true;}}// 其他地址不攔截:字典數(shù)據(jù)和文件上傳的接口for (String urlConfig : config.getOtherConfigs()) {if (StringUtils.contains(url, urlConfig)) {logger.info("其他非攔截地址" + url);return true;}}// 驗(yàn)證token是否存在logger.info("Authorization:" + token);if (StringUtils.isEmpty(token)) {logger.info("token參數(shù)為空");return false;}// 獲取redis中的session_key和openidString rd_session = redisTemplate.opsForValue().get(token);if (rd_session == null) {logger.info("token失效:" + token);return false;}logger.info("token存在,驗(yàn)證成功!");return true;}
3、小程序緩存
在web開發(fā)中我們通常將session信息放入cookie中,但是小程序沒有cookie,所以需要借助緩存來實(shí)現(xiàn)cookie功能。用戶第一次登陸成功后,會(huì)返回該用戶對應(yīng)的token,并放入storage緩存中,每次請求都會(huì)帶上去請求,向第三方服務(wù)器認(rèn)證身份。
wx.setStorageSync('id', res.data.object.id)var value = wx.getStorageSync('id')wx.setStorageSync('token', res.header.Authorization) //同步存 tokenwx.setStorageSync('openid', res.data.object.openid) //同步存 tokenwx.setStorageSync('userState', res.data.object.userState)getApp().globalData.user_wxNickname = res.data.object.wxNickname;getApp().globalData.user_userIcon = res.data.object.userIcon
小程序的登陸就是這幾個(gè)大的步驟,按照微信官方文檔來開發(fā),也需要避開一些小坑。
- 請求微信的接口時(shí)一定需要注意請求格式,直接寫在路徑后面的參數(shù),絕對不能換其他方式。
- 封裝的請求參數(shù),一定需要注意大小寫問題,appid和appId區(qū)別很大。
- 請求出錯(cuò)的時(shí)候,多看看文檔的錯(cuò)誤碼,相信可以幫助你。
總結(jié)
以上是生活随笔為你收集整理的微信小程序中用户登录和登录态维护的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。