生活随笔
收集整理的這篇文章主要介紹了
微信小程序中用户登录和登录态维护
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
微信小程序和以前的web項目不同,他是前后端分離的應用,之前我們的傳統登錄有web服務器提供Session維護, 后端在返回結果給前端web項目時,帶上cookie,且以cookie值為key存儲用戶信息到session中,前端web項目在再以后端返回的結果中,得到相應cookie的值,再一次以同樣的方式將cookie值返回給前端瀏覽器客戶端,這樣,后面每次瀏覽器客戶端請求時都會帶上cookie。微信小程序中沒有cooike,那么接下來我們來看下小程序如何登錄,以及如何維護微信小程序的登錄態(Session)。
官方登錄流程
直接引用官方的登錄文檔,我們的登錄維護都是按照這個文檔進行的開發,登錄流程圖如下圖所示:
1、在小程序中獲取微信用戶的登錄憑證(code)
小程序的登錄直接使用官方api接口wx.login(),從微信的官方服務器換取接口憑證code。
然后在小程序的app.js和后臺進行交互,將code發給自己的后臺服務器進行登錄換取token。
// 登錄
wx.login({
success: res => {
var that = this;
// 發送 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,我們后臺再次請求微信的服務器獲取微信用戶的信息,也就是openid和session_key。
try {// url 地址微信規定只能這樣拼接String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + wechatConfig.getAppid() + "&secret="+ wechatConfig.getSecret() + "&js_code=" + code + "&grant_type=authorization_code";logger.info("發送獲取openid請求url:" + url);String result = httpApiService.doPost(url);logger.info("請求結果:" + result);ObjectMapper objectMapper = new ObjectMapper();// json 轉對象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
這里微信有一個規定,參數值只能拼接在后面,不能通過HttpClient的map參數放上去,需要注意一下。
通過這個接口的調用,可以拿到用戶openid,和session_key,現在當前登錄的賬戶就在微信的服務器中產生了登錄態。
但是微信的官方文檔提示開發者,為了安全起見,需要第三方服務器自己定義一個登陸態,并且把如何定義session的規則告訴了。
我們拿到了openid和session_key,將用戶的openid存入數據庫,通過加密算法把openid和session_key加密生成3rd_session:
// 3、獲取自定義登陸態生成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,為了用戶的操作提供認證,在用戶登陸成功時,在header中攜帶token返回給用戶客戶端,用戶沒帶token請求,或者是token失效,都會請求失敗。
使用攔截器處理用戶的token認證,將http請求中帶的認證信息和redis的對比,如果存在沒失效,直接授權用戶請求,失效則攔截用戶的請求。
/*** 前置處理器* @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;}}// 其他地址不攔截:字典數據和文件上傳的接口for (String urlConfig : config.getOtherConfigs()) {if (StringUtils.contains(url, urlConfig)) {logger.info("其他非攔截地址" + url);return true;}}// 驗證token是否存在logger.info("Authorization:" + token);if (StringUtils.isEmpty(token)) {logger.info("token參數為空");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存在,驗證成功!");return true;}
3、小程序緩存
在web開發中我們通常將session信息放入cookie中,但是小程序沒有cookie,所以需要借助緩存來實現cookie功能。用戶第一次登陸成功后,會返回該用戶對應的token,并放入storage緩存中,每次請求都會帶上去請求,向第三方服務器認證身份。
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
小程序的登陸就是這幾個大的步驟,按照微信官方文檔來開發,也需要避開一些小坑。
- 請求微信的接口時一定需要注意請求格式,直接寫在路徑后面的參數,絕對不能換其他方式。
- 封裝的請求參數,一定需要注意大小寫問題,appid和appId區別很大。
- 請求出錯的時候,多看看文檔的錯誤碼,相信可以幫助你。
總結
以上是生活随笔為你收集整理的微信小程序中用户登录和登录态维护的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。