Springboot实现微信登录
一、登录流程
微信小程序登录流程涉及到三个角色:小程序、开发者服务器、微信服务器
三者交互步骤如下:
第一步:小程序
通过wx.login()获取code。
第二步:小程序
通过wx.request()发送code到开发者服务器。
第三步:开发者服务器
接收小程序发送的code,并携带appid、appsecret(这两个需要到微信小程序后台查看)、code发送到微信服务器
。
第四步:微信服务器
接收开发者服务器发送的appid、appsecret、code进行校验。校验通过后向开发者服务器
发送session_key、openid。
第五步:开发者服务器
自己生成一个skey(自定义登录状态)与openid、session_key进行关联,并存到数据库中(mysql、redis等)。
第六步:开发者服务器
返回生成skey(自定义登录状态)到小程序。
第七步:小程序
存储skey(自定义登录状态)到本地。
第八步:小程序
通过wx.request()发起业务请求到开发者服务器
,同时携带skey(自定义登录状态)。
第九步:开发者服务器
接收小程序
发送的skey(自定义登录状态),查询skey在数据库中是否有对应的openid、session_key。
第十步:开发者服务器
返回业务数据到小程序
。
二、搭建Springboot工程
略
三、整合微信登录
controller接口
import com.system.common.core.domain.AjaxResult;
import com.system.common.core.domain.entity.SysUser;
import com.system.common.core.domain.model.LoginUser;
import com.system.framework.web.service.TokenService;
import com.system.system.domain.wx.RemoteWxResult;
import com.system.system.domain.wx.WeChatUserInfo;
import com.system.system.domain.wx.WxRowData;
import com.system.system.service.ISysUserService;
import com.system.web.core.config.WeChatUtil;
import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Date;
@RestController
@Api(tags = "微信用户登录")
@RequestMapping("wx")
public class WeChatUserLoginController {
@Resource
private ISysUserService iSysUserService;
@Autowired
private WeChatUtil weChatUtil;
/**
* 微信用户登录详情
*/
@ApiImplicitParams({
@ApiImplicitParam(value = "微信用户信息", name = "weChatUserInfo", required = true, paramType = "body", dataType = "WeChatUserInfo", dataTypeClass = WeChatUserInfo.class)
})
@ApiOperation(value = "微信用户登录详情", notes = "微信用户登录详情", httpMethod = "POST")
@PostMapping("/login")
public AjaxResult user_login(@RequestBody WeChatUserInfo weChatUserInfo) throws Base64DecodingException {
// 2.开发者服务器 登录凭证校验接口 appId + appSecret + 接收小程序发送的code
RemoteWxResult SessionKeyOpenId = weChatUtil.getSessionKeyOrOpenId(weChatUserInfo.getCode());
// 3.接收微信接口服务 获取返回的参数
String openid = SessionKeyOpenId.getOpenid();
String sessionKey = SessionKeyOpenId.getSession_key();
// 用户非敏感信息:rawData
// 签名:signature
WxRowData rawDataJson = weChatUserInfo.getRawData();
// 4.校验签名 小程序发送的签名signature与服务器端生成的签名signature2 = sha1(rawData + sessionKey)
// String signature2 = DigestUtils.sha1Hex(weChatUserInfo.getRawData() + sessionKey);
// if (!weChatUserInfo.getSignature().equals(signature2)) {
// return ResultInfo.error( "签名校验失败");
//}
//encrypteData比rowData多了appid和openid
//JSONObject userInfo = WeChatUtil.getUserInfo(weChatUserInfo.getEncrypteData(),
// sessionKey, weChatUserInfo.getIv());
// 5.根据返回的User实体类,判断用户是否是新用户,是的话,将用户信息存到数据库;不是的话,更新最新登录时间
SysUser sysUser = iSysUserService.selectUserByUserName(openid);
if (sysUser == null) {
// 用户信息入库
// 新增用户到数据库
//略
iSysUserService.insertUser(sysUser1);
} else {
// 已存在,更新用户登录时间
}
// uuid生成唯一key,用于维护微信小程序用户与服务端的会话(或者生成Token)
//略
//6. 把新的skey返回给小程序
return AjaxResult.success();
}
}
远程调用返回实体
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @Author codertl
* @Date 2022/4/7
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RemoteWxResult implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户唯一标识
*/
private String openid;
/**
* 会话密钥
*/
private String session_key;
}
工具类
import com.alibaba.fastjson.JSON;
import com.system.system.domain.wx.RemoteWxResult;
import com.system.system.feign.WxRemoteClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@Configuration
public class WeChatUtil {
@Value("${wx.miniapp.configs.appid}")
private String appId;
@Value("${wx.miniapp.configs.secret}")
private String secret;
@Autowired
private WxRemoteClient wxRemoteClient;
public RemoteWxResult getSessionKeyOrOpenId(String code) {
//发送post请求读取调用微信接口获取openid用户唯一标识
String remoteAuthCode2Session = wxRemoteClient.remoteAuthCode2Session(appId, secret, code, "authorization_code");
return JSON.parseObject(remoteAuthCode2Session, RemoteWxResult.class);
}
}
前端传入实体类
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel(value = "WeChatUserInfo", description = "微信用户信息")
@Data
public class WeChatUserInfo {
/**
* 微信返回的code
*/
@ApiModelProperty(value = "微信返回的code", required = true)
private String code;
/**
* 非敏感的用户信息
*/
@ApiModelProperty(value = "非敏感的用户信息", required = true)
private WxRowData rawData;
/**
* 签名信息
*/
@ApiModelProperty(value = "签名信息", required = true)
private String signature;
/**
* 加密的数据
*/
@ApiModelProperty(value = "加密的数据", required = true)
private String encrypteData;
/**
* 加密密钥
*/
@ApiModelProperty(value = "加密密钥", required = true)
private String iv;
}
通过openFeign调用微信auth.code2Session 官网地址: https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html
pom.xml
<!-- SpringBoot的依赖配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.5.9</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>3.0.4</version>
</dependency>
wxClient
package com.system.system.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Map;
/**
* @Author codertl
* @Date 2022/04/07
*/
@FeignClient(url = "https://api.weixin.qq.com/sns", name = "wxLogin")
public interface WxRemoteClient {
/**
* 远程调用登录接口
* @param appid
* @param secret
* @return
*/
@GetMapping(value = "/jscode2session")
String remoteAuthCode2Session(
@RequestParam("appid") String appid,
@RequestParam("secret") String secret,
@RequestParam("js_code") String jsCode,
@RequestParam("grant_type") String grantType
);
}
application.yml
# 微信登录相关
wx:
miniapp:
configs:
appid: # 添加自己的appid
secret: # 添加自己的secret
<template>
<view>
<view class="index-bg">
<image src="../../static/wxlogin.png" mode="widthFix"></image>
<view class="index-content">
<view><button class="index-btn" @click="login()">微信一键登录/注册</button></view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
watch: {
},
methods:{
login() {
uni.login({
provider: 'weixin',
success: function (loginRes) {
// 获取用户信息
uni.getUserInfo({
provider: 'weixin',
success: function (infoRes) {
uni.request({
url: "http://localhost:8010/wx/login",
method: "POST",
header: {
'content-type': 'application/json'
},
data:{
code: loginRes.code, //临时登录凭证
rawData: infoRes.rawData, //用户非敏感信息
signature: infoRes.signature, //签名
encrypteData: infoRes.encryptedData, //用户敏感信息
iv: infoRes.iv //解密算法的向量
},
success:function(res){
console.log(res)
if(res.data.code == 200) {
console.log("登录成功", res.data.msg)
} else{
console.log("登录失败")
}
},
fail: function(error) {
//调用服务端登录接口失败
console.log(error);
}
})
}
});
}
});
}
},
onLoad() {
},
}
</script>
<style scoped lang="less">
.index-bg {
width: 100%;
padding-top: 20%;
}
.index-bg image {
width: 100%;
height: 100%;
}
.index-content {
width: 500rpx;
margin: 40% auto;
}
.index-btn {
background-color: #2b90fa;
color: #fff;
font-size: 32rpx;
width: 500rpx;
}
</style>
本文来自博客园,作者:CoderTL,转载请注明原文链接:https://www.cnblogs.com/codertl/p/16114260.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix