微信小程序 java实现登录界面_spring mvc框架实现微信小程序登录(前台+后台)...

本文详细介绍了微信小程序的登录流程,包括用户授权、前端登录实现、后端登录验证与用户信息处理。使用SSM(Spring MVC + Spring + MyBatis)框架,通过微信官方接口获取并解密用户信息,实现用户登录功能。同时,文章提到了在用户授权失败或登录错误时的处理方式。
摘要由CSDN通过智能技术生成

本文将详细的介绍微信小程序的登录流程以及在ssm框架下如何实现小程序用户登录(日后补上过滤器的配置。。。)

登录流程概要

主要的登录流程可以参考官方提供的一张流程图:

026ac9e1c3af5a34ed46f12c9beb2b95.png

1.微信前台页面:

在微信版本更新之后,提高了安全机制,我们需要为用户提供一个授权按钮,让用户同意授权,页面中的button必须包含 open-type="getUserInfo"这个属性:

一般授权页面如下:

1. 同意当前小程序获取我的微信头像;

2. 同意当前小程序获取我的微信昵称等其他信息;

bc4cc3473ca6d54a5689bf0471aa4063.png

2.登录前台实现

当用户登录时,我们先去判断小程序缓存中用户的token存不存在:

-----如果存在,将token传到后台去检查redis缓存中的用户信息是否失效:

-----如果失效,前台将用户信息删除,重新调用登录接口。

-----未失效,返回原页面,后台更新缓存失效时间。

-----如果不存在,前台调用官方提供的小程序登录接口:wx.login(),获得它返回的code:

-----code获取成功,前台调用wx.getSetting()获取授权以及用户的授权配置:

-----用户授权成功,前台调用wx.getUserInfo()获取encryptedData(密文)和 iv(偏移向量)

------以上都获取成功后,我们将code,encryptedData和iv全部传到后台。

(code用来换取openid和sessionKey,encryptedData和iv用来获得并解密用户信息)

-----如果后台获取用户信息成功,返回token和用户信息到前台,前台小程序在缓存中更新token和用户信息。

登录成功。

-----------------------任意一个步骤失败,提示用户无法登录。

微信小程序前台登录函数如下(下面这个函数较长,可以拆分,看的更清晰):

login: function () {

let that = this;

let token = wx.getStorageSync("token");

console.log("进入页面登录开始取token"+token);

if (token) {

console.log("如果token存在");

wx.request({

url: urlMangerData.api0_check_token,///wxma/user/check-token

data: {

token: token

},

success: function (res) {

console.log("前台token存在,校验token后返回值"+JSON.stringify(res));

//如果后台缓存已经不在了

if (!res.data.success) {

console.log("如果后台缓存已经失效了,小程序清空token和userinfo和openid");

wx.removeStorageSync("token");

wx.removeStorageSync("userInfo");

that.login();

} else {

console.log("后台缓存中的信息也存在,直接返回");

// 回到原来的地方

wx.navigateBack();

}

}

});

}

console.log("如果token不存在");

//小程序登录,

wx.login({

success: function (res) {

if(res.code){

wx.getSetting({

success: res2 => {

if (res2.authSetting["scope.userInfo"]) {

wx.getUserInfo({

success:datas=>{

console.log("开始获取code和一些加密过的用户信息" + res.code);

console.log("datas.encryptedData" + datas.encryptedData);

wx.request({

url: urlMangerData.api0_loginAuth,

data: {

code: res.code,

encryptedData: datas.encryptedData,

iv: datas.iv

},

header: {

'content-type': 'application/json'

},

success: function (res) {

console.log("后台成功后得到返回值" + res.data.code);

if(res.data.code != 0) {

console.log("后台登录错误")

wx.hideLoading();

wx.showModal({

title: "提示",

content: "无法登录,请重试",

showCancel: false

});

return;

}

console.log("存储用户信息token" + res.data.token);

console.log("存储用户信息userInfo" + JSON.stringify(res.data.wxMaUserInfoExtends));

wx.setStorageSync("token", res.data.token);

wx.setStorageSync("userInfo", res.data.wxMaUserInfoExtends);

wx.setStorageSync("user_id", res.data.wxMaUserInfoExtends.user_id);

wx.navigateBack();

}

});//request

}

})//getuserinfo

}

}

})//getsetting

}

}//success

})

}

再贴一下第一次登录时,控制台打印信息:

da01586867fea05926da0aa2191ff56e.png

3.登录后台实现

当用户登录时,先检查前台传来的token在redis中是否存在:存在即更新redis中用户信息的失效时间,不存在则返回登录失效信息。

前台获得失效信息后,正常去调用获取用户信息接口,传入code,encryptedData和iv:

controller层:

@RequestMapping(value = "/loginAuth", method = RequestMethod.GET, produces = "application/json; charset=utf-8")public String loginAuth(String code,String encryptedData,String iv) throwsWxErrorException {if(StringUtils.isBlank(code)) {return "empty jscode";

}//处理登录授权 获得openid和sessionkey,生成userid 并将session存到缓存中

WxMaAuthResult result =weixinMaService.dealLoginAuth(code,encryptedData,iv);returnJsonUtils.objectToJson(result);

}

service层:

/*** 处理小程序登录授权*/@OverridepublicWxMaAuthResult dealLoginAuth(String code,String data,String iv) {

WxMaJscode2SessionResult session=newWxMaJscode2SessionResult();//调微信官方接口获得sesssion_key openid存到 session对象里

try{

//code换取sessionKey

session=wxMaService.getUserService().getSessionInfo(code);this.logger.info(session.getSessionKey());this.logger.info(session.getOpenid());

}catch(WxErrorException e) {this.logger.error("获得sessionKey失败", e);

}

WxMaAuthResult wxMaAuthResult= newWxMaAuthResult();

//该类用来存储用户信息

WxMaUserInfoExtends wxMaUserInfoExtends= newWxMaUserInfoExtends();

WxMaUserInfo wxMaUserInfo= newWxMaUserInfo();//暂时写死失效时间

int expire=3600;

String sessionKey=session.getSessionKey();

String rawData=StringEscapeUtils.unescapeHtml4(data);//解密用户信息

try{

//sessionkey data iv 解密用户信息

wxMaUserInfo= this.wxMaService.getUserService().getUserInfo(sessionKey, data, iv);

}catch(Exception e) {//TODO Auto-generated catch block

logger.error("解密用户信息失败");

e.printStackTrace();

}

BeanUtils.copyProperties(wxMaUserInfo, wxMaUserInfoExtends);

String third_session=Base64UUID.ramdomID();

wxMaAuthResult.setToken(third_session);

String user_id=Base64UUID.ramdomID();

wxMaUserInfoExtends.setUser_id(user_id);//通过openid获取或新增用户信息

if(wxMaUserMapper.countAny(session.getOpenid())>0){//存在 数据库更新

wxMaUserMapper.addWxMaUser(wxMaUserInfoExtends);//这里是将用户信息存到redis

wxMaAuthSessionStorage.addWxMaSession(expire,third_session,wxMaUserInfoExtends);//不把openId传到前台

wxMaUserInfo.setOpenId("");

wxMaAuthResult.setIsReg(true);

wxMaAuthResult.setSuccess(true);

wxMaAuthResult.setWxMaUserInfoExtends(wxMaUserInfoExtends);

}else{//不存在 数据库保存信息

wxMaUserMapper.addWxMaUser(wxMaUserInfoExtends);

wxMaAuthSessionStorage.addWxMaSession(expire,third_session,wxMaUserInfoExtends);

wxMaUserInfo.setOpenId("");

wxMaAuthResult.setSuccess(true);

wxMaAuthResult.setIsReg(false);

wxMaAuthResult.setWxMaUserInfoExtends(wxMaUserInfoExtends);

} returnwxMaAuthResult;

}

实体类:

public classWxMaUserInfoExtends{privateString user_id;privateString openId;privateString nickName;privateString gender;privateString language;privateString city;privateString province;privateString country;privateString avatarUrl;privateString unionId;privateDate create_date;

...

}

public class WxMaAuthResult extendsWxMaJscode2SessionResult{privateString code;privateString token;private int expiresIn = -1;

Boolean isReg= false; //是否保存过用户信息

private booleansuccess;privateWxMaUserInfoExtends wxMaUserInfoExtends;

...

}

注:还有一些是api提供的。

redis存取方法:

@AutowiredprivateJedisClient jedisClient;/*** 存放token和用户信息*/

//内部事务回滚不影响外部事务

@Transactional(propagation =Propagation.REQUIRES_NEW)

@Overridepublic void addWxMaSession(intexpire,String token,WxMaUserInfoExtends wxMaUserInfoExtends) {String json=JsonUtils.objectToJson(wxMaUserInfoExtends);try{

jedisClient.set(token, json);

jedisClient.expire(token, expire);

}catch(Exception e) {

e.printStackTrace();

}

}

//从缓存中获取用户信息

@OverridepublicWxMaAuthResult getWxMaSessionBy3rdKey(String token) {

WxMaAuthResult wxMaAuthResult= newWxMaAuthResult();try{

String json=jedisClient.get(token);if(json == null) {

wxMaAuthResult.setSuccess(false);returnwxMaAuthResult;

}

wxMaAuthResult.setSuccess(true);

WxMaUserInfoExtends wxMaUserInfoExtends= JsonUtils.jsonToPojo(json, WxMaUserInfoExtends.class);

wxMaAuthResult.setWxMaUserInfoExtends(wxMaUserInfoExtends);returnwxMaAuthResult;

}catch(Exception e) {//TODO Auto-generated catch block

e.printStackTrace();

wxMaAuthResult.setSuccess(false);returnwxMaAuthResult;

}

}

注:这里使用了binarywang(一个github上的开源开发者)提供的API,该API封装了调用微信小程序官方接口的方法,并提供了一些小程序登录信息和用户信息的实体类,非常方便,有需要可以下载下来用:https://github.com/binarywang

后台大体流程:

1.我们用code去换取sessionKey和openId,再通过sessionKey,encryptedData和iv来解密用户信息(解密过程已经封装好了)。

2.生成一个随机字符串,将它作为key(token),用户信息作为value存入redis缓存并设置或更新失效时间。

3.返回登录结果和用户信息到前台。

原文出处:https://www.cnblogs.com/xjx199403/p/10785356.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值