实现于springboot中
依据b站视频写出的: 点击此处进行观看
然后记录于此处.
首先微信登陆的流程为: (可以去微信开发者平台看)
- 第一步:请求CODE 若提示“该链接无法访问”,请检查参数是否填写错误,如redirect_uri的域名与审核时填写的授权域名不一致或 scope 不为snsapi_login。
https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
- 第二步: 通过 code 获取access_token
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
- 获取用户个人信息(UnionID机制)
https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
开始代码操作…
注: 这里是用户前端访问后台指定接口后, 自动跳转到微信提供的扫描二维码页面进行扫描的, 此处后台的扫描登陆没有跟前台交互, 下边vue代码中有如何让二维码在我们指定的地方进行显示, 如果需要获取用户登陆后的信息, 后台代码中有描述怎么进行获取, 也就是我们的 login 方法, 用户确认登陆后微信平台会回调我们这个接口.
(1)导入依赖
<!-- 实体类工具类 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- hutool 工具类依赖此处用来连接 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.5.6</version>
</dependency>
<!-- 转换JSON工具类 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>
<!-- 视图解析器 此处我用到了最后一个将数据返回给前端 根据实际情况使用 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
(2)准备好接收微信回调给的token,以及获取用户信息的User实体类
Token类 (接收微信返回的token信息)
// 微信返回的token信息
@AllArgsConstructor
@Data
@NoArgsConstructor
public class Token {
String access_token; // 接口调用凭证
String expires_in; // access_token接口调用凭证超时时间,单位(秒)
String refresh_token; // 用户刷新access_token
String openid; // 授权用户唯一标识
String scope; // 用户授权的作用域,使用逗号(,)分隔
String unionid; // 当且仅当该网站应用已获得该用户的 userinfo 授权时,才会出现该字段
}
User类 (接收微信返回的用户信息使用)
/**
* 微信服务器返回的用户信息封装类
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
/**
* 微信扫码登录后台返回的是json数据
* 例如:
* {
"openid":"OPENID",
"nickname":"NICKNAME",
"sex":1,
"province":"PROVINCE",
"city":"CITY",
"country":"COUNTRY",
"headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
"privilege":[
"PRIVILEGE1",
"PRIVILEGE2"
],
"unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
*/
// 用户的唯一标识
private String openid;
// 用户的昵称
private String nickname;
// 用户的性别
private String sex;
// 用户所在的省份
private String province;
// 用户所在的城市
private String city;
// 用户所在的国家
private String country;
// 用户的头像URL地址
private String headimgurl;
}
主要实现接口
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.gsz.weixinlogin.pojo.Token;
import com.gsz.weixinlogin.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Slf4j
@Controller // 处理微信登陆
public class WxLoginController {
// appid与密钥
private String appid = "你的appid";
private String secret = "密钥";
// 微信回调 如网站以上线就是网页的地址 和接口
private String nwct = "http://www.txjava.cn/weixinLogin";
// (一)用户访问此接口 会进入微信的二维码扫描页面 让用户进行扫描 然后微信进行跳转
@RequestMapping("/login")
public String test(){
// 重定向请求的地址 微信的地址 访问之后会生成一个二维码
String url = "https://open.weixin.qq.com/connect/qrconnect?" +
"appid=" + appid + // 微信申请的 appid
"&redirect_uri=" + nwct + // 微信回调的地址 + 访问的借口 例: www.baidu.com/weixindenglu
"&response_type=code&" + // 是固定形式code值
"scope=snsapi_login" + // 应用授权作用域 网页应用目前仅填写snsapi_login
"&state=STATE" + // 用于保持请求和回调的状态,授权请求后原样带回给第三方 可用于防止 csrf 攻击
"#wechat_redirect"; // 这一个是连接上参数默认的 不用动
// 进行重定向 是以上咱们拼接的那个微信地址 url
return "redirect:" + url;
}
/**
* (二)用户确认登陆后 微信那边回调的接口
* @param code 登陆成功后微信回调的参数
* @param model 用来存储共享域的 测试使用
* @return 返回一个字符串 进行跳转页面
*/
@GetMapping("/weixinLogin")
public String login(String code,Model model) {
// 判断微信是否返回了code code不存在则是
if (code == null){
throw new RuntimeException("用户拒绝登陆!");
}
// 定义地址 填写第一步的code信息 获取token
String token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="
+ appid + "&secret=" + secret + "&code=" + code + "&grant_type=authorization_code";
// 使用Java代码 发送请求
try {
// HttpUtil工具类发送get请求 (通过 code 获取access_token)
String token_content = HttpUtil.get(token_url);
// 把json字符串转换成对象 其中有微信返回的凭证
Token token = JSON.parseObject(token_content, Token.class);
log.info("获取到的凭证:{}",token);
// (三) 获取到接口调用凭证 获取用户的信息
String userStr = "https://api.weixin.qq.com/sns/userinfo?" +
"access_token=" + token.getAccess_token() +
"&openid=" + token.getOpenid();
// 发送get请求 并接收 微信返回的用户信息(json)
String user = HttpUtil.get(userStr);
// 将微信返回的json信息转换为对象
User user1 = JSON.parseObject(user, User.class);
log.info("解析出的用户信息:{}",user1);
// 如果用户性别 == 0 为男 == 1 为女 设置一下
if ("0".equals(user1.getSex())){
user1.setSex("男");
}else {
user1.setSex("女");
}
// 存储到共享域中 为了前端获取 可以修改可以不用这个 此处我为了当时的测试
model.addAttribute("user",user1);
// 跳转的页面
return "UserHtml";
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("微信扫描登录异常...");
}
}
}
在vue中我们该怎么指定显示这个二维码让用户扫描呢?
此处记录了两种方式: 一种是基于组件的,一种是基于实例的,不管哪种都需要导入微信的那个js文件.
http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js.最终获取用户确认登陆后的信息还是请求到了后端进行用户信息的获取.
<template>
<div class="home">
<el-button @click="ck">点击登陆</el-button>
<!-- 方式一图片显示的位置 -->
<div id="login_container"> </div>
<!-- 方式二 组件法 npm install vue-wxlogin --save-dev 命令安装此组件 thname="white" 为白色的字 -->
<wxlogin
appid="你的appid"
:scope="'snsapi_login'"
:theme="'black'"
:redirect_uri='encodeURIComponent("http://www.txjava.cn/weixinLogin")'>
</wxlogin>
</div>
</template>
<!-- 第二种方式可以这样导入 也可以使用以下的方式引入 -->
<!--<script src="http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>-->
<script>
// 引入微信的js弹出必须导入 第一种方式必须这样导入 先得存在那个js文件 然后import
import weixin from "../wexin"
// 第二种方式 使用一个组件
import wxlogin from 'vue-wxlogin';
export default {
name: 'HomeView',
data(){
return {
isShowForm : true
}
},
components: { // 导入组件
wxlogin
},
methods:{
ck(){// 点击切换微信扫码登录这一项,并向微信扫码登录 第一种方式
this.isShowForm=false;
// 微信登录第一步:申请微信登录二维码
let _this = this;
new WxLogin({
id: "login_container", // 二维码显示的位置
appid: "你的appid", // 这个appid要填死
scope: "snsapi_login", //
// 扫码成功后重定向的接口
redirect_uri: "http://www.txjava.cn/weixinLogin",
// state填写编码后的url
// state: encodeURIComponent(window.btoa("http://127.0.0.1:80" + _this.$route.path)),
state: "STATE",
// 调用样式文件
// href: "data:text/css;base64,LmJveHsKICBiYWNrZ3JvdW5kOmJsb2NrOwp9",
});
}
}
}
</script>
因为第一种方式需要导入这个微信的js文件 所有我下载下来了并且放入到了一个js文件中(WxLogin.js).
!function (a, b, c) {
function d(a) {
var c = "default";
a.self_redirect === !0 ? c = "true" : a.self_redirect === !1 && (c = "false");
var d = b.createElement("iframe"),
e = "https://open.weixin.qq.com/connect/qrconnect?appid=" + a.appid + "&scope=" + a.scope + "&redirect_uri=" + a.redirect_uri + "&state=" + a.state + "&login_type=jssdk&self_redirect=" + c + '&styletype=' + (a.styletype || '') + '&sizetype=' + (a.sizetype || '') + '&bgcolor=' + (a.bgcolor || '') + '&rst=' + (a.rst || '');
e += a.style ? "&style=" + a.style : "", e += a.href ? "&href=" + a.href : "", d.src = e, d.frameBorder = "0", d.allowTransparency = "true", d.scrolling = "no", d.width = "300px", d.height = "400px";
var f = b.getElementById(a.id);
f.innerHTML = "", f.appendChild(d)
}
a.WxLogin = d
}(window, document);
如果导入以上js文件后报错,那么添加以下代码,初始化js也可以
mounted() {
//初始化微信js
const script = document.createElement('script')
script.type = 'text/javascript'
script.src = 'https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js'
document.body.appendChild(script)
}