vue+springboot实现微信扫码登陆(二维码由后端传给vue)
1.设计思路思路参考:一篇大神的笔记主要就是通过用sessionid请求微信服务器生成临时二维码,客户扫码后微信服务器会将对应数据发给本地服务器,本地根据openid在关联关系表中找出userid,取出用户信息,放入缓存中,即为登录成功。我使用的是微信测试公众号,未关注公众号和已关注公众号触发的事件不同。2.获取二维码字节流/*** 获取生成临时二维码的ticke...
·
1.设计思路
思路参考:一篇大神的笔记
主要就是通过用sessionid请求微信服务器生成临时二维码,客户扫码后微信服务器会将对应数据发给本地服务器,本地根据openid在关联关系表中找出userid,取出用户信息,放入缓存中,即为登录成功。我使用的是微信测试公众号,未关注公众号和已关注公众号触发的事件不同。
2.获取二维码字节流
/**
* 获取生成临时二维码的ticke
*/
public static String createForeverTicket(String accessToken, String sceneId) {
String ticke = null;
String requestUrl = " https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN";
requestUrl = requestUrl.replace("TOKEN", accessToken);
String ticketParam = "{\"expire_seconds\": 1200, \"action_name\": \"QR_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": \"" + sceneId + "\"}}}";
String reString = CheckoutUtil.httpsRequest(requestUrl, "POST", ticketParam, null);
JSONObject jsonObject = JSONObject.parseObject(reString);
if (null != jsonObject) {
try {
ticke = jsonObject.getString("ticket");
} catch (Exception e) {
int err = jsonObject.getInteger("errcode");
String errormsg = jsonObject.getString("errmsg");
System.out.println("获取失败errcode=" + err + "errmsg=" + errormsg);
}
}
return ticke;
}
/**
* 换取二维码字节流
*
*/
public static byte[] sendHttpByGet(String ticket){
String requestUrl = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET";
requestUrl = requestUrl.replace("TICKET", ticket);
try {
URL urlGet = new URL(requestUrl);
URLConnection urlConnection = urlGet.openConnection();
InputStream is = urlConnection.getInputStream();
byte[] bytes = toByteArray(is);
is.close();
return bytes;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* InputStream转化为byte[]数组
*/
public static byte[] toByteArray(InputStream input) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
}
return output.toByteArray();
}
3.将二维码以图片流传给前端
QRcode.getQRcodeImg(request)输出的就是上面的byte[] sendHttpByGet
@GetMapping("/getImg")
public void getImg(HttpServletRequest request, HttpServletResponse response) throws IOException {
//设置响应类型
response.setContentType("image/png");
//输出图片到页面
PrintWriter out = response.getWriter();
InputStream is = new ByteArrayInputStream(QRcode.getQRcodeImg(request));
int a = is.read();
while (a != -1) {
out.print((char) a);
a = is.read();
}
out.flush();
out.close();
}
4.前端接收显示二维码
async WeChatToken() {
const { data: res } = await this.$http.get('WeChatToken/getImg', {
responseType: 'arraybuffer'
});
this.imgUrl = 'data:image/png;base64,' + btoa(new Uint8Array(res).reduce((data, byte) => data + String.fromCharCode(byte), ''));
this.dialogVisible = true;
this.timer = setInterval(async () => {
const { data: res } = await this.$http.get('WeChatToken/isLogin');
console.log(res);
if (res.status == '200') {
//登陆成功
}
}, 2000);
}
5.服务器接收扫码事件
我是将sessionid做为key对应的用户数据为value存入application
@PostMapping
protected void toVatifyTokenPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
//防止进行post提交和响应的消息乱码
request.setCharacterEncoding("UTF-8");
response.setHeader("Content-type", "text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
try{
//将发送过来的消息XML形式转为map内容
Map<String , String> map = MessageUtils.xmlToMap(request);
String fromUserName = map.get("FromUserName");
String toUserName = map.get("ToUserName");
String msgType = map.get("MsgType");
String content = map.get("Content");
String message = null ;
if(MessageUtils.MESSAGE_EVENT.equals(msgType)){
String eventType = map.get("Event");
//订阅事件 或 未关注扫描二维码事件
if(MessageUtils.MESSAGE_SUBSCRIBE .equals(eventType)){
message = meUtils.initText(fromUserName,toUserName , MessageUtils.menuText());
}else if(MessageUtils.MESSAGE_SCANCODE .equals(eventType)) {
//进行的是扫码事件
String key = map.get("EventKey");
message = meUtils.initText(fromUserName,toUserName , "已验证信息,请稍后。");
User selUser= weChatServiceImpl.selUserByOpenid(fromUserName);
System.out.println(key);
ServletContext application = request.getSession().getServletContext();
application.setAttribute(key,selUser);
}else if(MessageUtils.MESSAGE_UNSUBSCRIBE .equals(eventType)) {
//进行的是取消关注事件
weChatServiceImpl.delUserOpenid(fromUserName);
}
}else {
message = meUtils.initText(fromUserName,toUserName , "自动回复:测试服务器,功能未完善。");
}
out.print(message);
}catch (Exception e){
e.printStackTrace();
}finally {
out.close();
}
}
6.vue前端获取到二维码后会定时查询是否登陆成功
/**
*判断扫码登陆
*/
@GetMapping("/isLogin")
public JSONResult isLogin(HttpServletRequest request) {
ServletContext application = request.getSession().getServletContext();
String sessionId=request.getSession().getId();
User user = (User) application.getAttribute(sessionId);
if(user!=null){
application.removeAttribute(sessionId);
return JSONResult.custom("200", getToken(user), user);
}
return JSONResult.failMsg("未登录");
}
更多推荐
已为社区贡献7条内容
所有评论(0)