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


前言

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


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

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

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

属性类型必填说明
appidstring小程序 appId
secretstring小程序 appSecret
js_codestring登录时获取的 code,可通过wx.login获取
grant_typestring授权类型,此处只需填写 authorization_code

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

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

二、微信用户数据库设计

代码如下:

CREATE TABLE `wechat_user` (
  `id` 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同级

package com.ruoyi.common.core.domain.entity;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import com.ruoyi.common.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类

在com.echain.common.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 accessToken;
}
    /**
     * 小程序登录
     *
     * @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.success().put("data", res);
        }
        catch (Exception e)
        {
            String msg = "接口异常";
            if (StringUtils.isNotEmpty(e.getMessage()))
            {
                msg = e.getMessage();
            }
            return AjaxResult.error(msg);
        }
    }

5.开放接口

com.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微信小程序登录授权

  • 12
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 18
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值