ruoyi的springboot微信小程序登录实现方式


前言

主要是讲ruoyi前后端分离框架,springboot的微信小程序的实现方式,ruoyi的登录一般只针对账号密码登录,微信小程序登录却没有,实际上稍微改造一下就可以用。


一、微信小程序的登录接口

根据微信开放文档,微信有提供自己的登录接口,可用于现有的微信用户,并且授予基本信息

GET https://api.weixin.qq.***/sns/jscode2session
入参如下:

属性 类型 必填 说明
appid string 小程序 appId
secret string 小程序 appSecret
js_code string 登录时获取的 code,可通过wx.login获取
grant_type string 授权类型,此处只需填写 authorization_code

这个接口就是咱们要的登录接口,但是需要有js_code才行,这个js_code我们一般要前端返回即可,至于appid和secret需要去微信公众平台那边获取,一般需要有开发者权限(在管理者的手上)

返回的类型我就不写那么详细了,咱们需要openid也就是用户唯一标识,这个咱们需要存到数据库里面,以及用openidsessionKey作为账号密码登录

二、微信用户数据库设计

代码如下:

CREATE TABLE `wechat_user` (
  `userId` bigint NOT NULL AUTO_INCREMENT ***MENT '自增主键',
  `openid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL ***MENT '用户的唯一标识',
  `unionid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL ***MENT '公众号的唯一标识',
  `nickname` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL ***MENT '昵称',
  `name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL ***MENT '真实姓名',
  `phonenumber` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL ***MENT '手机号码',
  `gender` tinyint(1) DEFAULT '0' ***MENT '性别,0-未知 1-男性,2-女性',
  `region` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL ***MENT '地区',
  `avatar_url` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL ***MENT '用户头像URL',
  `subscribe` tinyint NOT NULL DEFAULT '0' ***MENT '是否订阅公众号 0-否 1-是',
  `del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '0' ***MENT '删除标志(0代表存在 2代表删除)',
  `create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL ***MENT '创建者',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ***MENT '创建时间',
  `update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL ***MENT '更新者',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ***MENT '更新时间',
  `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL ***MENT '备注',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `uk_openid` (`openid`) USING BTREE ***MENT '唯一索引,用于加速查找'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC ***MENT='微信用户表';

数据库设计尽量照着ruoyi的格式来,然后一些基本信息看自己需求来,我是偷懒了直接让gpt帮我生成了,最主要的是拿到openid,然后unionid一般也是根据需求来,咱们暂时用不上,不过也会预留字段。

三、springboot登录接口实现

1.新建实体WechatUser

***mon模块下新建一个WechatUser,和SysUser同级

java">package ***.ruoyi.***mon.core.domain.entity;

import org.apache.***mons.lang3.builder.ToStringBuilder;
import org.apache.***mons.lang3.builder.ToStringStyle;

import ***.ruoyi.***mon.core.domain.BaseEntity;


/**
 * 微信用户实体
 * 
 * @author Ricky
 */
public class WechatUser extends BaseEntity
{
    private static final long serialVersionUID = 1L;

    /** 自增主键 */
    @TableId
    private Long id;

    /** 用户的唯一标识 */
    @Excel(name = "用户的唯一标识")
    private String openid;

    /** 微信会话秘钥 */
    @TableField(exist = false)
    private String sessionKey;

    /** 公众号的唯一标识 */
    @Excel(name = "公众号的唯一标识")
    private String unionid;

    /** 昵称 */
    @Excel(name = "昵称")
    private String nickname;

    /** 手机号码 */
    @Excel(name = "手机号码")
    private String phonenumber;

    /** 性别,0-未知 1-男性,2-女性 */
    @Excel(name = "性别,0-未知 1-男性,2-女性")
    private Integer gender;

    /** 地区 */
    @Excel(name = "地区")
    private String region;

    /** 用户头像URL */
    @Excel(name = "用户头像URL")
    private String avatarUrl;
	// 后面跟数据库设计一致
}

2.修改LoginUser类

在***.echain.***mon.core.domain.model.LoginUser的类加一个wechatUser,生成gettersetter(用了lombok可不加),并且改写getPasswordgetUsername 方法

/**
     * 微信用戶信息
     */
    private WechatUser wechatUser;
    
    public WechatUser getWechatUser() {
        return wechatUser;
    }

    public void setWechatUser(WechatUser wechatUser) {
        this.wechatUser = wechatUser;
    }
    
	@JsonIgnore
    @Override
    public String getPassword()
    {
        return user != null ? user.getPassword() : wechatUser.getSessionKey();
    }

    @Override
    public String getUsername()
    {
        return user != null ? user.getUserName() : wechatUser.getOpenId();
    }

3.增加wxLogin接口

这个接口是为了走SpringSecurity的登录验证方式,跟ruoyi原来的类似

public String wxLogin(String openId, String sessionKey, WechatUser user) {
        LoginUser loginUser = new LoginUser(user);
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(openId, sessionKey);
        authenticationToken.setDetails(loginUser);
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        // 生成token
        return tokenService.createToken(loginUser);
    }

这里是用了微信小程序登录接口返回的openIdsessionKey作为账号密码,由于sessionKey老是变动,咱们就不需要存数据库,而openid是唯一的,需要存数据库

4.微信小程序登录接口

先添加一个调微信小程序提供的开放登录方法

    /**
     * 获取微信小程序的基本信息
     * @param code
     * @return
     * @throws JsonProcessingException
     */
    public static Map<String, Object> getWechatBaseInfo(String code) throws JsonProcessingException {
        // 调用微信认证接口,获取 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_URLAPP_IDSECRETcode是前面说的链接和入参

然后写springboot的登录接口(补充WeChatReq和WechatResp类)

@Data
public class WeChatReq {
    private String code;
    private String jscode;
    private String encryptedData;
    private String iv;
    private String phonenumber;
    private String sessionKey;
}
@Data
public class WechatResp {
    private String code;
    private String jscode;
    private String openId;
    private String unionId;
    private String sessionKey;
    private String a***essToken;
}
    /**
     * 小程序登录
     *
     * @param weChatReq 小程序wx.login返回的临时凭证
     * @return
     */
    @PostMapping("/mini/login")
    @Transactional
    public AjaxResult login(@RequestBody WeChatReq 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))
            {
                return AjaxResult.error("登录凭证不能为空");
            }
            // 查询是否已存在用户,如果不存在就把微信用户登录记录存储起来,这里我引入了mybatis-plus,如果没有的话可以直接写一个根据openid获取用户信息的方法.
            QueryWrapper<WechatUser> wrapper = new QueryWrapper<>();
            wrapper.eq("openid", openId);
            WechatUser user = userServiceImpl.getOne(wrapper);
            if(Objects.isNull(user)){
                user = new WechatUser();
                    user.setOpenid(openId);
                    user.setCreateBy("mini");
                    user.setCreateTime(new Date());
                    user.setUpdateBy("mini");
                    user.setUpdateTime(new Date());
                    userServiceImpl.insertWechatUser(user);
                }
            }
            WechatResp resp = new WechatResp();
            resp.setJscode(weChatReq.getJscode());
            resp.setCode(weChatReq.getCode());
            resp.setSessionKey(sessionKey);
            resp.setOpenId(openId);
            JSONObject res = new JSONObject();
            // 生成令牌
            String token = loginService.wxLogin(openId, sessionKey, user);
            res.put(Constants.TOKEN, token);
            return AjaxResult.su***ess().put("data", res);
        }
        catch (Exception e)
        {
            String msg = "接口异常";
            if (StringUtils.isNotEmpty(e.getMessage()))
            {
                msg = e.getMessage();
            }
            return AjaxResult.error(msg);
        }
    }

5.开放接口

***.echain.framework.config.SecurityConfig的configure方法放行登录接口,在前面的/login、/captchaImage接口加一个/mini/login(根据自身需求加)

// 对于登录login 验证码captchaImage 允许匿名访问
.antMatchers("/login", "/captchaImage", "/mini/login").anonymous()

到这里就大功告成了,存数据库这个操作我就不详细说了,还有要注意如果没有引入mybatis-plusQueryWrapper那边需要改成根据openid获取用户信息的方法

总结

实现之后,就能跟以前ruoyi的登录,通过token携带来访问接口,要注意的是这边的权限控制就失效了,需要自己改写权限的分配,因为以前是跟着sys_user这个表的用户走的,这里不仔细讲了,一般微信小程序这边不需要做用户角色权限分配,可以自己加一层新的。

参考博客:RuoYi-Vue微信小程序登录授权

转载请说明出处内容投诉
CSS教程_站长资源网 » ruoyi的springboot微信小程序登录实现方式

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买