当前位置: 首页 > news >正文

用户模块:微信小程序授权、登录、用户信息管理

用户模块:微信小程序授权、登录、用户信息管理

“你是谁?”——这是任何互联网应用的第一个问题。在无人售货柜项目中,用户模块就是回答这个问题的,它承载着微信授权登录、JWT签发、用户信息管理的全部职责。

一、微信小程序登录流程

微信小程序登录是一个三方交互的过程。很多新手在这里被绕晕,画张图就清楚了:

小程序端 后端服务 微信API | | | |--1.wx.login()------>| | |<--code--------------| | | |--2.发code/appid/secret->| | |<--openid+session_key--| | |--3.签发JWT------------>| |<--返回token----------| | |--4.后续请求带token-->| | | |--校验JWT-------------->|

步骤拆解:

  1. 调用wx.login()获取临时code(有效期5分钟,一次性)
  2. 后端拿code + appid + appsecret请求微信接口jscode2session
  3. 微信返回openid(用户唯一标识)和session_key
  4. 后端用openid创建/查找用户,签发 JWT
  5. 小程序端拿到 JWT,后续请求都带在Authorization头里

二、用户表设计

CREATETABLE`user`(`id`bigintNOTNULLCOMMENT'用户ID,雪花算法',`openid`varchar(64)NOTNULLCOMMENT'微信openid',`unionid`varchar(64)DEFAULTNULLCOMMENT'微信unionid(多平台打通用)',`nickname`varchar(50)DEFAULTNULLCOMMENT'昵称',`avatar`varchar(500)DEFAULTNULLCOMMENT'头像URL',`phone`varchar(11)DEFAULTNULLCOMMENT'手机号(AES加密存储)',`status`tinyintNOTNULLDEFAULT'1'COMMENT'1-正常 2-封禁 3-注销',`last_login_time`datetimeDEFAULTNULLCOMMENT'最后登录时间',`create_time`datetimeNOTNULLDEFAULTCURRENT_TIMESTAMP,`update_time`datetimeNOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP,PRIMARYKEY(`id`),UNIQUEKEY`uk_openid`(`openid`))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COMMENT='用户表';

设计注意点:

  • openid必加唯一索引,是最核心的查询条件
  • phone建议加密存储,保护隐私
  • status不要用deleted,用户注销和逻辑删除是有区别的

三、后端登录与 JWT 签发

@RestController@RequestMapping("/user")publicclassUserController{@AutowiredprivateUserServiceuserService;@PostMapping("/login")publicResult<LoginVO>login(@RequestBodyLoginDTOdto){returnResult.ok(userService.login(dto.getCode()));}}@ServicepublicclassUserService{@Value("${wechat.appid}")privateStringappid;@Value("${wechat.secret}")privateStringsecret;@AutowiredprivateRestTemplaterestTemplate;@AutowiredprivateRedisTemplate<String,Object>redisTemplate;/** * 微信登录:code换openid,签发JWT */publicLoginVOlogin(Stringcode){// 1. 调用微信接口获取openid + session_keyStringurl=String.format("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",appid,secret,code);WechatSessionResponseresp=restTemplate.getForObject(url,WechatSessionResponse.class);if(resp.getErrcode()!=null&&resp.getErrcode()!=0){thrownewBusinessException("微信登录失败: "+resp.getErrmsg());}// 2. 根据openid查找或创建用户Stringopenid=resp.getOpenid();Useruser=userMapper.selectByOpenid(openid);if(user==null){user=newUser();user.setId(IdUtil.getSnowflake().nextId());user.setOpenid(openid);user.setStatus(1);user.setLastLoginTime(LocalDateTime.now());userMapper.insert(user);}else{// 检查用户状态if(user.getStatus()!=1){thrownewBusinessException("账号状态异常,请联系客服");}user.setLastLoginTime(LocalDateTime.now());userMapper.updateById(user);}// 3. 缓存 session_key(后续解密手机号等场景需要)redisTemplate.opsForValue().set("session_key:"+openid,resp.getSessionKey(),7,TimeUnit.DAYS);// 4. 签发JWTStringtoken=JwtUtil.generateToken(user.getId(),openid);// 5. 返回LoginVOvo=newLoginVO();vo.setToken(token);vo.setUserId(user.getId());vo.setIsNew(user.getCreateTime().equals(user.getUpdateTime()));returnvo;}}

四、用户信息授权

在微信 2021 年改版后,wx.getUserProfile需要用户点击按钮触发。后端接收后更新用户表:

@PostMapping("/update/profile")publicResult<Void>updateProfile(@RequestBodyProfileDTOdto){LonguserId=UserContext.getCurrentUserId();// 从JWT中解析Useruser=newUser();user.setId(userId);user.setNickname(dto.getNickname());user.setAvatar(dto.getAvatarUrl());userMapper.updateById(user);// 清除用户缓存redisTemplate.delete("user:info:"+userId);returnResult.ok();}

五、手机号授权与解密

手机号获取需要解密,因为微信传给后端的手机号是加密的:

@PostMapping("/bind/phone")publicResult<Void>bindPhone(@RequestBodyPhoneDTOdto){LonguserId=UserContext.getCurrentUserId();Stringopenid=userMapper.selectById(userId).getOpenid();// 从Redis获取session_keyStringsessionKey=(String)redisTemplate.opsForValue().get("session_key:"+openid);if(sessionKey==null){thrownewBusinessException("session_key过期,请重新登录");}// AES解密手机号StringphoneJson=WxUtil.decrypt(dto.getEncryptedData(),sessionKey,dto.getIv());WxPhoneInfophoneInfo=JSONUtil.toBean(phoneJson,WxPhoneInfo.class);// 加密后存入DBUseruser=newUser();user.setId(userId);user.setPhone(AesUtil.encrypt(phoneInfo.getPurePhoneNumber()));userMapper.updateById(user);returnResult.ok();}

六、JWT 签发与网关校验

publicclassJwtUtil{@Value("${jwt.secret}")privateStringsecret;@Value("${jwt.expiration:86400000}")// 默认24小时privatelongexpiration;publicStringgenerateToken(LonguserId,Stringopenid){returnJwts.builder().setSubject(String.valueOf(userId)).claim("openid",openid).setIssuedAt(newDate()).setExpiration(newDate(System.currentTimeMillis()+expiration)).signWith(SignatureAlgorithm.HS256,secret).compact();}publicClaimsparseToken(Stringtoken){returnJwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();}}

在 Spring Cloud Gateway 中统一校验:

@ComponentpublicclassAuthFilterimplementsGlobalFilter{@OverridepublicMono<Void>filter(ServerWebExchangeexchange,GatewayFilterChainchain){Stringpath=exchange.getRequest().getURI().getPath();// 白名单放行if(path.startsWith("/user/login"))returnchain.filter(exchange);Stringtoken=exchange.getRequest().getHeaders().getFirst("Authorization");if(token==null||!token.startsWith("Bearer ")){returnunauthorized(exchange,"未登录");}try{Claimsclaims=JwtUtil.parseToken(token.substring(7));// 检查Token是否在黑名单中(用户注销后)if(redisTemplate.hasKey("token:blacklist:"+token)){returnunauthorized(exchange,"Token已失效");}// 将userId写入请求头,下游服务直接读取exchange.getRequest().mutate().header("X-User-Id",claims.getSubject());}catch(Exceptione){returnunauthorized(exchange,"Token无效或已过期");}returnchain.filter(exchange);}}

七、用户状态管理

正常(1) ──→ 封禁(2) ←── 运营手动操作 │ └──→ 注销(3) ←── 用户主动注销(7天冷静期)

用户登录时检查 status,非正常状态拒绝登录。封禁状态保留 openid,防止换号绕封禁。

八、Feign 对外提供用户信息

@FeignClient(name="user-service",path="/user")publicinterfaceUserFeignClient{@GetMapping("/info/{id}")Result<UserVO>getUserById(@PathVariable("id")Longid);@GetMapping("/info/openid/{openid}")Result<UserVO>getUserByOpenid(@PathVariable("openid")Stringopenid);}

九、Redis 缓存 + Token 黑名单

// 缓存用户信息publicUserVOgetUserById(Longid){Stringkey="user:info:"+id;UserVOcached=(UserVO)redisTemplate.opsForValue().get(key);if(cached!=null)returncached;Useruser=userMapper.selectById(id);UserVOvo=BeanUtil.copyProperties(user,UserVO.class);redisTemplate.opsForValue().set(key,vo,1,TimeUnit.HOURS);returnvo;}// 注销/登出时,Token加入黑名单publicvoidlogout(Stringtoken){Claimsclaims=JwtUtil.parseToken(token);longttl=claims.getExpiration().getTime()-System.currentTimeMillis();redisTemplate.opsForValue().set("token:blacklist:"+token,"1",ttl,TimeUnit.MILLISECONDS);}

十、常见问题

1. session_key 过期怎么办?

session_key 本身无有效期,但微信建议不自行维护过期。通常做法是每次wx.login都获取新的 session_key,缓存覆盖旧的即可。

2. Token 续期策略

推荐双 Token机制:access_token 24小时 + refresh_token 30天。access_token 过期后用 refresh_token 换新,refresh_token 过期则重新走微信授权登录。

3. 多端登录互踢

无人售货柜小程序一般单设备登录,不需要考虑互踢。如果需要,可以用openid → current_token映射,在签发新 Token 时把旧 Token 加入黑名单。

用户模块是"面门",写好不难,难的是想清楚每一个状态流转和安全边界。

http://www.jsqmd.com/news/1317552/

相关文章:

  • 2026深度测评10款降AI率软件红黑榜!优缺点无保留曝光,达标率直逼行业天花板
  • 2026年精选:湖南饮料OEM代工厂怎么选?深度解析代工模式与优质供应商 - 装修教育财税推荐2026
  • JS扩展运算符与Object.assign深度对比与应用指南
  • LVDS数据之位对齐
  • 2026 年至今,资兴热门的水下失物打捞生产厂家哪个好,你丢的东西,居然能这样从水底找回来?90%的人都不知道这个靠谱法子。 - 鉴选官
  • Linux字符设备驱动开发入门:从file_operations到内存设备实现
  • 改进BPSO算法在配电网重构中的应用与Matlab实现
  • 2026 年当下,厦门正规的耐候钢板景观墙实力厂家推荐几家,别再只看大理石了!这款能扛住几十年风吹雨打的景观墙,比普通材质省3倍维护费-冠煌金属 - 企业推荐管【认证】
  • 2026 年新消息:上海有实力的岩板吊装厂商有哪些,为啥几块大板能稳稳贴在墙上?这门手艺藏着你不知道的安全门道 - 企业信息推荐【官方】
  • AI概念风格渲染实战手册:从零搭建Stable Diffusion+ControlNet工业级渲染管线(附GitHub万星项目调优秘钥)
  • 2026 年新发布:海淀正规的铸铁闸门制造企业全面解析与选购指南,水渠漏失的幕后推手,竟是这款不起眼的工业利器-仁禹水利机械 - 企业信息推荐【官方】
  • LangGraph智能体开发:图结构与实战优化
  • 重磅上新:推荐杭州买ec系统公司怎么选择 - 品牌推广大师
  • 2026年评价高的张家港资质代办公司推荐哪家强? - 品牌排行榜
  • 临床预测模型快速入门:基于Python与AutoML的实践指南
  • Studio5000 v33虚拟机环境搭建与优化指南
  • 对比4个主流项目课程设置,找到综合实力最强的EMBA
  • ATAT 完全使用教程
  • 科研绘图进阶:解析1200张Nature插图,掌握顶级期刊图表设计
  • Matlab实现综合能源系统优化调度关键技术
  • 2026 年更新:老城正规的煤场地磅公司怎么联系,这台测煤重的设备,竟藏着不少能帮矿主年省十几万的门道? - 行业严选官
  • Windows系统下PS4手柄无法识别的终极排查与驱动冲突解决指南
  • 2026年8月优质的手工型板直销厂家推荐,水平线模具/铸铝铁模具/静压线模具/铁件产品加工,手工型板生产厂家有哪些 - 品牌推荐师
  • 支付对接:微信/支付宝支付、回调解析、订单核销
  • UiPath定时任务全攻略:从Cron表达式到生产级调度实战
  • XIAO nRF54L15 Sense开发板:集成传感器套件与低功耗物联网应用实战
  • 基于MQTT协议实现Reachy Mini机械臂与Home Assistant智能家居系统集成
  • 2026 年现阶段新疆性价比高的明杆式铸铁闸门工厂哪家好,用了这玩意儿,老灌区再也没出过堤防水漫的糟心事? - 企业推荐官【认证】
  • GitHub SSH密钥配置指南:安全访问私有仓库
  • 2026 年现阶段广宗正规的洁净车间订制厂家哪家靠谱,车间里看不见的“隐形卫士”,竟能藏住千万级产品的命脉?-萧宝净化板 - 企业官方推荐【认证】