文章目录
前言
主要是讲ruoyi前后端分离框架,springboot的微信小程序的实现方式,ruoyi的登录一般只针对账号密码登录,微信小程序登录却没有,实际上稍微改造一下就可以用。
一、微信小程序的登录接口
根据微信开放文档,微信有提供自己的登录接口,可用于现有的微信用户,并且授予基本信息
GET https://api.weixin.qq.com/sns/jscode2session
入参如下:
属性类型必填说明appidstring是小程序 appIdsecretstring是小程序 appSecretjs_codestring是登录时获取的 code,可通过wx.login获取grant_typestring是授权类型,此处只需填写 authorization_code
这个接口就是咱们要的登录接口,但是需要有js_code才行,这个js_code我们一般要
前端返回
即可,至于appid和secret需要去微信公众平台那边获取,一般需要有开发者权限(在管理者的手上)
返回的类型我就不写那么详细了,咱们需要
openid
也就是用户唯一标识,这个咱们需要存到数据库里面,以及用
openid
和
sessionKey
作为账号密码登录
二、微信用户数据库设计
代码如下:
CREATE TABLE `wechat_user` (
`userId` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`openid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户的唯一标识',
`unionid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '公众号的唯一标识',
`nickname` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '昵称',
`name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '真实姓名',
`phonenumber` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '手机号码',
`gender` tinyint(1) DEFAULT '0' COMMENT '性别,0-未知 1-男性,2-女性',
`region` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '地区',
`avatar_url` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '用户头像URL',
`subscribe` tinyint NOT NULL DEFAULT '0' COMMENT '是否订阅公众号 0-否 1-是',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)',
`create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `uk_openid` (`openid`) USING BTREE COMMENT '唯一索引,用于加速查找'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='微信用户表';
数据库设计尽量照着ruoyi的格式来,然后一些基本信息看自己需求来,我是偷懒了直接让gpt帮我生成了,最主要的是拿到openid,然后unionid一般也是根据需求来,咱们暂时用不上,不过也会预留字段。
三、springboot登录接口实现
1.新建实体WechatUser
在
common
模块下新建一个
WechatUser
,和
SysUser
同级
packagecom.ruoyi.common.core.domain.entity;importorg.apache.commons.lang3.builder.ToStringBuilder;importorg.apache.commons.lang3.builder.ToStringStyle;importcom.ruoyi.common.core.domain.BaseEntity;/**
* 微信用户实体
*
* @author Ricky
*/publicclassWechatUserextendsBaseEntity{privatestaticfinallong serialVersionUID =1L;/** 自增主键 */@TableIdprivateLong id;/** 用户的唯一标识 */@Excel(name ="用户的唯一标识")privateString openid;/** 微信会话秘钥 */@TableField(exist =false)privateString sessionKey;/** 公众号的唯一标识 */@Excel(name ="公众号的唯一标识")privateString unionid;/** 昵称 */@Excel(name ="昵称")privateString nickname;/** 手机号码 */@Excel(name ="手机号码")privateString phonenumber;/** 性别,0-未知 1-男性,2-女性 */@Excel(name ="性别,0-未知 1-男性,2-女性")privateInteger gender;/** 地区 */@Excel(name ="地区")privateString region;/** 用户头像URL */@Excel(name ="用户头像URL")privateString avatarUrl;// 后面跟数据库设计一致}
2.修改LoginUser类
在com.echain.common.core.domain.model.LoginUser的类加一个
wechatUser
,生成
getter
和
setter
(用了lombok可不加),并且改写
getPassword
和
getUsername
方法
/**
* 微信用戶信息
*/privateWechatUser wechatUser;publicWechatUsergetWechatUser(){return wechatUser;}publicvoidsetWechatUser(WechatUser wechatUser){this.wechatUser = wechatUser;}@JsonIgnore@OverridepublicStringgetPassword(){return user !=null? user.getPassword(): wechatUser.getSessionKey();}@OverridepublicStringgetUsername(){return user !=null? user.getUserName(): wechatUser.getOpenId();}
3.增加wxLogin接口
这个接口是为了走SpringSecurity的登录验证方式,跟ruoyi原来的类似
publicStringwxLogin(String openId,String sessionKey,WechatUser user){LoginUser loginUser =newLoginUser(user);UsernamePasswordAuthenticationToken authenticationToken =newUsernamePasswordAuthenticationToken(openId, sessionKey);
authenticationToken.setDetails(loginUser);SecurityContextHolder.getContext().setAuthentication(authenticationToken);// 生成tokenreturn tokenService.createToken(loginUser);}
这里是用了微信小程序登录接口返回的
openId
和
sessionKey
作为账号密码,由于sessionKey老是
变动
,咱们就不需要存数据库,而openid是唯一的,需要存数据库
4.微信小程序登录接口
先添加一个调微信小程序提供的开放登录方法
/**
* 获取微信小程序的基本信息
* @param code
* @return
* @throws JsonProcessingException
*/publicstaticMap<String,Object>getWechatBaseInfo(String code)throwsJsonProcessingException{// 调用微信认证接口,获取 session_key 和 openid 等信息String url =String.format(GET_AUTH_URL,APP_ID,WechatConfig.SECRET, code);String response = restTemplate.getForObject(url,String.class);return objectMapper.readValue(response,HashMap.class);}
其中
GET_AUTH_URL
、
APP_ID
、
SECRET
、
code
是前面说的链接和入参
然后写springboot的登录接口(补充WeChatReq和WechatResp类)
@DatapublicclassWeChatReq{privateString code;privateString jscode;privateString encryptedData;privateString iv;privateString phonenumber;privateString sessionKey;}@DatapublicclassWechatResp{privateString code;privateString jscode;privateString openId;privateString unionId;privateString sessionKey;privateString accessToken;}
/**
* 小程序登录
*
* @param weChatReq 小程序wx.login返回的临时凭证
* @return
*/@PostMapping("/mini/login")@TransactionalpublicAjaxResultlogin(@RequestBodyWeChatReq weChatReq){// 调用微信认证接口,获取 session_key 和 openid 等信息Map<String,Object> resultMap;try{String jscode = weChatReq.getJscode();
resultMap =getWechatBaseInfo(weChatReq.getJscode());String sessionKey =(String) resultMap.get("session_key");String openId =(String) resultMap.get("openid");// 用户登录凭证(有效期五分钟)if(StringUtils.isEmpty(jscode)){returnAjaxResult.error("登录凭证不能为空");}// 查询是否已存在用户,如果不存在就把微信用户登录记录存储起来,这里我引入了mybatis-plus,如果没有的话可以直接写一个根据openid获取用户信息的方法.QueryWrapper<WechatUser> wrapper =newQueryWrapper<>();
wrapper.eq("openid", openId);WechatUser user = userServiceImpl.getOne(wrapper);if(Objects.isNull(user)){
user =newWechatUser();
user.setOpenid(openId);
user.setCreateBy("mini");
user.setCreateTime(newDate());
user.setUpdateBy("mini");
user.setUpdateTime(newDate());
userServiceImpl.insertWechatUser(user);}}WechatResp resp =newWechatResp();
resp.setJscode(weChatReq.getJscode());
resp.setCode(weChatReq.getCode());
resp.setSessionKey(sessionKey);
resp.setOpenId(openId);JSONObject res =newJSONObject();// 生成令牌String token = loginService.wxLogin(openId, sessionKey, user);
res.put(Constants.TOKEN, token);returnAjaxResult.success().put("data", res);}catch(Exception e){String msg ="接口异常";if(StringUtils.isNotEmpty(e.getMessage())){
msg = e.getMessage();}returnAjaxResult.error(msg);}}
5.开放接口
com.echain.framework.config.SecurityConfig的
configure
方法放行登录接口,在前面的/login、/captchaImage接口加一个/mini/login(根据自身需求加)
// 对于登录login 验证码captchaImage 允许匿名访问.antMatchers("/login","/captchaImage","/mini/login").anonymous()
到这里就大功告成了,存数据库这个操作我就不详细说了,还有要注意如果没有引入
mybatis-plus
,
QueryWrapper
那边需要改成根据openid获取用户信息的方法
总结
实现之后,就能跟以前ruoyi的登录,通过token携带来访问接口,要注意的是这边的
权限控制
就失效了,需要自己改写权限的分配,因为以前是跟着
sys_user
这个表的用户走的,这里不仔细讲了,一般微信小程序这边不需要做用户角色权限分配,可以自己加一层新的。
参考博客:RuoYi-Vue微信小程序登录授权
版权归原作者 Black·Tea 所有, 如有侵权,请联系我们删除。