网站首页 > 技术文章 正文
前言
Hi,大家好,我是希留。
很多PC端的网站都有使用微信扫码登录的功能,不需要输入用户名和密码,打开手机微信扫一扫,就可以自动登录,确实很便捷。那么,它是如何实现快捷登录的呢?
本篇文章就带大家通过真实项目的登录场景来了解一下微信扫码登录的整个流程。如果对你有帮助的话,还不忘点赞转发支持一下,感谢!
目录
- 一、功能背景
- 二、扫码登录原理
- 三、代码实现
- 四、实现效果图
一、功能背景
公司的平台登录页面要新增一种微信扫码登录的方式。用户可以选择使用微信账号登录,点击微信账号登录的时候,弹出一个微信登录的二维码,扫码确认后判断该用户账号是否和平台账号绑定了。若绑定了则完成登录。若未绑定,则在登录按钮下出现一行提示文字。登录后自动绑定该账号。下次就可直接用微信登录。
平台是前后端分离的项目,所用的技术栈是SpringBoot+Vue。
二、扫码登录原理
网站应用微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统。
微信OAuth2.0授权登录让微信用户使用微信身份安全登录第三方应用或网站,在微信用户授权登录已接入微信OAuth2.0的第三方应用后,第三方可以获取到用户的接口调用凭证(access_token),通过access_token可以进行微信开放平台授权关系接口调用,从而可实现获取微信用户基本开放信息和帮助用户实现基础开放功能等。
微信OAuth2.0授权登录目前支授权码(authorization_code)模式,适用于拥有服务端的应用授权。该模式整体流程为:
1.第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;
2.通过code参数加上AppID和AppSecret等,通过API换取access_token;
3.通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作
简单来说,就是用户在生成二维码的页面扫码后进入回调地址,回调地址可以获取临时票据code,通过code可以获取accessToken,通过accessToken则可以获取用户的全部信息;通过获取的该用户信息与要登录的第三方应用账号一对一绑定,即可实现使用微信扫码登录第三方应用;
三、代码实现
1.准备工作
在微信开放平台(不是微信公众号平台)注册开发者帐号,并拥有一个已审核通过的网站应用,并获得相应的AppID和AppSecret,申请微信登录且通过审核后,可开始接入流程。(目前已不支持个人账号注册,需公司注册。)
新建一个网站应用
新建完成后,需要进行开发者认证。
设置回调域名
2.开始编写代码
编写前端代码:
点击微信登录,弹出登录二维码。回调地址的域名保持和开放平台设置的回调域名
<div v-if="showWxLogin">
<img src="@/assets/img/login/wx.jpg" alt="" />
<p style="margin-top:-30px"><a @click="onWxLogin" >微信账号登录</a></p>
</div>
<div v-if="showBinding">
<p ><input type="checkbox" id="checkbox" v-model="checkBinding">登录成功后关联微信,下次可用微信直接登录</p>
</div>
<a-modal :visible="wxLoginVisible"
:footer="false"
:maskClosable="false"
@cancel="wxLoginVisible = false">
<!-- 放置二维码的div -->
<div id="login_container">
<iframe></iframe>
</div>
</a-modal>
<a-modal :visible="bindingWxLoginVisible"
:footer="false"
:closable="false"
:maskClosable="false"
@cancel="bindingWxLoginVisible = false">
<p>您好,xxx</p>
<p>您还没有关联学习平台账号,请选择一项操作:</p>
<a-button size="small" @click="cancel">取消</a-button>
<a-button type="primary" size="small" @click="binding">登录现有账号</a-button>
</a-modal>
<script>
import wxlogin from '@/utils/wxLogin' // 引入生成微信二维码的js
watch: {
$route() {
/*监听路由是否有code值*/
if(this.$route.query.code != undefined) {
//请求后端微信登录接口
this.getWeixinLogin(this.$route.query.code,this.$route.query.state);
}
}
},
methods: {
async onWxLogin() {
// 生成微信登录二维码
this.wechatCode()
this.wxLoginVisible = true
},
async wechatCode () {
// 回调地址,域名请保持和设置的回调域名一致,前端的路由地址
let url = process.env.VUE_APP_LEARN_BASE_URL + "/#/login/student";
// appid
let wxAppId = process.env.VUE_APP_WX_APP_ID;
// 记住一定要注明文件类型是css
var blob = new Blob([""],{type: "text/css;charset=utf-8"});
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = function(e) {
var obj = new WxLogin({
self_redirect: false, // 值为true时,直接在二维码的弹窗中进行页面跳转及其余操作,
id:"login_container", // div的id
appid: wxAppId,
scope: "snsapi_login", //固定内容
redirect_uri:encodeURIComponent(url) // 回调地址
})
}
},
async getWeixinLogin(code) {
// 请求判断是否有绑定微信
let res = await api.student.wxLogin({ code: code })
if (res.code === 200) {
let data = res.data;
// 微信昵称
this.nickname = data.nickname;
// 微信登录
this.refreshToken = data.refresh_token;
// data.code == 100表示未绑定微信号
if (data.code === '100') {
this.wxLoginVisible = false;
// 弹出绑定微信账号页
this.bindingWxLoginVisible = true;
} else {
// 调转登录成功后页面
...
}
}
},
async cancel() {
this.bindingWxLoginVisible = false;
},
async binding() {
this.bindingWxLoginVisible = false;
this.checkBinding = true;
this.showBinding = true;
this.showWxLogin = false;
},
}
</script>
编写后端代码:
后端只需要提供两个接口,一个是校验该微信号是否绑定了平台用户的接口,一个是微信号与平台用户绑定的接口。请求微信接口信息可查看官方文档:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html
@GetMapping("/student/wxLogin")
public R wxLogin(String code){
if(StringUtils.isBlank(code)){
return R.fail("用户禁止授权");
}
//通过code获取access_token
String tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+appid+"&secret="+secret+"&code="+code+"&grant_type=authorization_code";
// 请求微信的接口,返回token信息
Token accessToken = JSON.parseObject(HttpClientUtil.doGet(tokenUrl), Token.class);
//获取用户信息
String userUrl = "https://api.weixin.qq.com/sns/userinfo?access_token="+accessToken.getAccess_token()+"&openid="+accessToken.getOpenid();
StudWx studWx = JSON.parseObject(HttpClientUtil.doGet(userUrl), StudWx.class);
//判断用户有没有绑定微信,如果没有绑定跳转到绑定页面;绑定了直接登陆
...
if(...){
//没有绑定微信,返回前端需要的信息,让前端跳转到绑定页面
...
}else{
//直接登陆
...
}
}
@PostMapping("/student/bdingLogin")
public R bdingLogin(@RequestBody LoginParam param){
//先判断账号是否已绑定微信
...
if(StringUtils.isNotBlank(openId)){
return R.fail("该账号已绑定微信");
}
//再登录,判断账号密码正不正确
R login = loginService.login(param);
//登陆成功并且选择了绑定微信账号
if(login.getCode()==200 && param.getBinding()){
//刷新token,防止过期
String resUrl = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid="+appid+"&grant_type=refresh_token&refresh_token="+ param.getRefreshToken();
Token token = JSON.parseObject(HttpClientUtil.doGet(resUrl), Token.class);
String userUrl = "https://api.weixin.qq.com/sns/userinfo?access_token="+token.getAccess_token()+"&openid="+token.getOpenid();
StudWx studWx = JSON.parseObject(HttpClientUtil.doGet(userUrl), StudWx.class);
//保存用户绑定微新号的相关操作
...
}
return R.ok();
}
四、实现效果图
五、结语
好了,以上就是整个微信扫码登录的流程以及实现了。其核心流程就是:打开页面生成微信登录二维码,扫码二维码登录,即可知道用户信息,通过该用户信息即可判断是否有与平台的用户账号关联,关联了的用户即可知道该微信号登录的是哪个用户,就可以实现登录的相关操作了,而无需在通过输入账号密码进行登录。
感谢大家的阅读,喜欢的朋友,欢迎点赞转发支持一下,感谢。
猜你喜欢
- 2024-10-10 让编辑器支持word的复制黏贴,支持截屏的黏贴
- 2024-10-10 大文件上传优化(切片、断点续传、秒传)
- 2024-10-10 你知道前端对图片的处理方式吗(前端实现图片编辑)
- 2024-10-10 JavaScript异步图像上传(javascript 异步操作)
- 2024-10-10 javascript对文件和进制操作的一些方法汇总
- 2024-10-10 Node + H5 实现大文件分片上传、断点续传
- 2024-10-10 input上传图片并压缩(vue,前端,js)
- 2024-10-10 leaflet地图截图批量导出(leaflet地图旋转)
- 2024-10-10 Spring WebSocket传递多媒体消息(websocket springmvc)
- 2024-10-10 JS上传文件判断文件类型(js如何判断文件是否存在)
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)