2021-0410 小程序学习记录-登录功能前后端实现及获取用户信息
1.小程序利用wx.login()函数获取登录凭证code。code每次调用都不一样,有效期5分钟,在服务器发送给微信接口服务验证一次后失效。
2.小程序将code发给服务器,服务器使用code在微信接口服务校验登录凭证,校验成功返回session_key(会话密钥)和openid,服务器生成token,并将其作为保存session数据的主键(自定义登录态)。随后将token返回给前端。
3.前端收到token并在本地保留,存入缓存。下一次登录时,先将token发送至服务器校验,验证通过则不用再次登录。
前端代码片段:
wx.login({
//此处做了封装,调用wx.login()函数便会自动接收回调参数res
success: res => {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
console.log('login code :' + res.code)
//利用post请求发送code至服务器,并接收回调成功参数
wx.request({
url: 'http://127.0.0.1:3000/login',
method: 'post',
data: {
code: res.code
},
success: res => {
console.log('token:' + res.data.token),
//将token保存在全局变量中
this.globalData.token = res.data.token,
//保存在缓存,下一次登录继续使用
wx.setStorage({
data: res.data.token,
key: 'token',
})
}
})
}
})
}
后端代码片段:
var db ={
session:{},
user:{}
}
app.post('/login',(req,res)=>{
//req为前端发过来的请求参数
console.log('login code:'+req.body.code)
var url='https://api.weixin.qq.com/sns/jscode2session?appid='+wx.appid+'&secret='+wx.secret+'&js_code='+req.body.code+'&grant_type=authorization_code'
request(url,(err,response,body)=>{
console.log('body:'+body)
var session =JSON.parse(body)
if(session.openid){
//定义token(定义登录态)作为查询标志,检验有效期
var token='token'+new Date().getTime()
//按照token保存session信息,键值对形式
db.session[token]=session
//根据openID保存程序用户的账户信息
if(!db.user[session.openid]){
db.user[session.openid]={
credit:100
}
}
}
//返回给前端token
res.json({token:token})
})
fs.writeFile('db.txt',db,function(err){
// console.log('Saved successfully'();
})
})
app.get('/checklogin',(req,res)=>{
var session=db.session[req.query.token]
console.log('checklogin:'+session)
res.json({is_login:session!==undefined})
})
此处只涉及前端
index.js
const app = getApp()
Page({
data: {
motto: 'Hello World',
userInfo: {},
hasUserInfo: false,
canIUse: wx.canIUse('button.open-type.getUserInfo'),
canIUseGetUserProfile: true,
canIUseOpenData: false // 如需尝试获取用户信息可改为false
},
// 事件处理函数
bindViewTap() {
wx.navigateTo({
url: '../logs/logs'
})
},
onLoad() {
if(app.globalData.userInfo){
this.setData({
userInfo:app.globalData.userInfo,
hasUserInfo:true
})
}
if (wx.getUserProfile) {
this.setData({
canIUseGetUserProfile: true
})
}
},
getUserProfile(e) {
// 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
wx.getUserProfile({
desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: (res) => {
console.log(res)
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
}
})
app.js
```javascript
onLaunch() {
// 登录
this.checkLogin(res=>{
console.log('is_login:',res.is_login)
if(!res.is_login){
this.login()
}
})
//读取用户设置
wx.getSetting({
success:res=>{
//是否同意获取用户信息
if(res.authSetting['scope.userInfo']){
wx.getUserProfile({
success:res=>{
console.log(res)
this.globalData.userInfo=res.userInfo
}
})
}
}
})
}
index.wxml
<view class="container">
<view class="userinfo">
<block wx:if="{{canIUseOpenData}}" class="userinfo-opendata">
<view class="userinfo-avatar" bindtap="bindViewTap">
<open-data type="userAvatarUrl">open-data>
view>
<open-data type="userNickName">open-data>
block>
<block wx:elif="{{!hasUserInfo}}">
<button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile"> 获取头像昵称 button>
<view wx:else> 请使用1.4.4及以上版本基础库 view>
block>
<block wx:else>
<image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover">image>
<text class="userinfo-nickname">{{userInfo.nickName}}text>
<text class="userinfo-nickname">{{userInfo.city}}text>
<text class="userGender" lang='zh CN'>text>
block>
view>
<view class="usermotto">
<text class="user-motto">{{motto}}text>
view>
<button bindtap="credit">获取用户积分button>
view>