若依框架v3.8.6实战:为你的小程序/APP快速接入独立用户体系与Token认证
2026/4/26 14:38:33 网站建设 项目流程

若依框架v3.8.6实战:构建独立移动端用户体系与Token认证全流程

在当今多端应用开发浪潮中,如何高效管理不同终端的用户体系成为开发者面临的普遍挑战。许多团队最初采用单一后台用户表(如SysUser)支撑所有业务,但随着移动端用户量增长,这种设计往往导致权限混乱、数据冗余和安全隐患。本文将深入探讨如何基于若依框架v3.8.6版本,从零构建一套完整的移动端专属用户体系(AppUser),并复用框架内置的安全组件实现高效认证。

1. 为什么需要独立移动端用户体系

后台管理系统用户移动端应用用户存在本质差异。后台用户通常是企业内部员工或管理员,需要细粒度的权限控制和操作日志追踪;而移动端用户更关注注册便捷性、社交属性和设备信息。混合存储这两种用户会导致:

  • 权限模型复杂化:移动端不需要RBAC等复杂权限控制
  • 字段冗余:移动端特有的设备ID、推送Token等字段对后台用户无意义
  • 安全风险:同一套密码策略可能无法满足两端不同的安全要求

通过创建独立的app_user表,我们可以实现:

CREATE TABLE `app_user` ( `user_id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID', `user_name` varchar(30) NOT NULL COMMENT '用户账号', `nick_name` varchar(30) NOT NULL COMMENT '用户昵称', `mobile` varchar(11) DEFAULT '' COMMENT '手机号码', `avatar` varchar(100) DEFAULT '' COMMENT '头像地址', `password` varchar(100) DEFAULT '' COMMENT '密码', `salt` varchar(50) DEFAULT '' COMMENT '盐', `status` char(1) DEFAULT '0' COMMENT '帐号状态', `device_id` varchar(64) DEFAULT '' COMMENT '设备唯一标识', `push_token` varchar(200) DEFAULT '' COMMENT '推送令牌', PRIMARY KEY (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='APP用户信息表';

提示:建议为移动端用户添加device_idpush_token等特有字段,便于后续消息推送和设备绑定功能实现

2. 核心组件设计与实现

2.1 实体类与数据层构建

com.ruoyi.common.core.domain.entity包下创建AppUser实体类时,需要注意与SysUser的差异处理:

public class AppUser extends BaseEntity { private Long userId; private String userName; private String nickName; private String mobile; private String avatar; private String password; private String salt; private String status; private String deviceId; // 移动端特有字段 private String pushToken; // 移动端特有字段 // 省略getter/setter }

Mapper接口设计应聚焦移动端特有需求:

public interface AppUserMapper { AppUser selectByMobile(String mobile); // 手机号登录专用 int updateDeviceInfo(AppUser appUser); // 设备信息更新 List<AppUser> selectByDeviceType(String deviceType); // 按设备类型查询 }

2.2 安全认证体系改造

若依原有的Token认证机制需要针对移动端进行适配。在AppTokenService中,我们增加了设备验证逻辑:

@Component public class AppTokenService { @Value("${token.appExpireTime}") private int appExpireTime; // 移动端可配置更长有效期 public String createAppToken(LoginAppUser loginAppUser) { // 验证设备合法性 if (!deviceService.validate(loginAppUser.getDeviceId())) { throw new ServiceException("设备验证失败"); } String token = IdUtils.fastUUID(); loginAppUser.setToken(token); refreshToken(loginAppUser); Map<String, Object> claims = new HashMap<>(); claims.put(Constants.LOGIN_APP_USER_KEY, token); return createToken(claims); } }

注意:移动端Token有效期通常设置更长(如7天),但需要通过刷新机制保证安全性

2.3 过滤器链改造

JwtAuthenticationTokenFilter中增加移动端请求识别逻辑:

@Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) { String uri = request.getRequestURI(); if (uri.startsWith("/app/")) { // 移动端认证流程 LoginAppUser appUser = appTokenService.getLoginAppUser(request); if (appUser != null) { appTokenService.verifyToken(appUser); SecurityContextHolder.getContext() .setAuthentication(new AppAuthenticationToken(appUser)); } } else { // 原有后台认证流程 super.doFilterInternal(request, response, chain); } }

3. 业务层最佳实践

3.1 登录流程优化

移动端登录通常支持多种方式,需要在AppLoginService中实现多因素认证:

public String login(LoginAppBody body) { // 1. 基础验证 AppUser user = StringUtils.isMobile(body.getUsername()) ? appUserMapper.selectByMobile(body.getUsername()) : appUserMapper.selectByUserName(body.getUsername()); // 2. 密码验证 if (!passwordService.matches(body.getPassword(), user)) { throw new ServiceException("密码错误"); } // 3. 设备绑定检查 deviceService.checkDevice(user.getUserId(), body.getDeviceId()); // 4. 生成Token LoginAppUser loginUser = new LoginAppUser(user); loginUser.setDeviceId(body.getDeviceId()); return appTokenService.createAppToken(loginUser); }

3.2 会话管理策略

移动端会话管理需要特殊处理:

场景后台用户策略移动端优化策略
超时时间30分钟固定动态超时(7天+滑动过期)
并发控制严格单设备登录多设备同时在线
失效通知即时跳转登录页静默刷新Token

实现滑动过期示例:

public void verifyToken(LoginAppUser loginUser) { long expireTime = loginUser.getExpireTime(); long currentTime = System.currentTimeMillis(); // 剩余时间不足20%时自动续期 if (expireTime - currentTime < expireTime * 0.2) { refreshToken(loginUser); } }

4. 接口设计与测试

4.1 控制器层实现

AppLoginController需要提供符合RESTful规范的API:

@RestController @RequestMapping("/app/auth") public class AppLoginController extends BaseController { @PostMapping("/login") public AjaxResult login(@Valid @RequestBody AppLoginBody body) { String token = loginService.login( body.getLoginType(), // 登录方式:密码、短信、第三方 body.getPrincipal(), // 主体:用户名/手机号 body.getCredential(), // 凭证:密码/验证码 body.getDeviceInfo() // 设备信息 ); return success().put("token", token); } @GetMapping("/userinfo") public AjaxResult userInfo() { LoginAppUser user = getLoginAppUser(); return success().put("user", user.getAppUser()); } }

4.2 Postman测试用例

登录接口测试:

POST /app/auth/login Content-Type: application/json { "loginType": "sms", "principal": "13800138000", "credential": "123456", "deviceInfo": { "deviceId": "iOS-12A365", "model": "iPhone13,4" } }

响应示例:

{ "code": 200, "msg": "操作成功", "data": { "token": "eyJhbGciOiJIUzI1NiJ9...", "expiresIn": 604800 } }

4.3 常见问题排查

问题1:Token失效但用户无感知

解决方案:实现静默刷新机制

// 前端拦截器示例 axios.interceptors.response.use(response => { return response; }, error => { if (error.response.status === 401 && !error.config._retry) { error.config._retry = true; return refreshToken().then(res => { store.commit('updateToken', res.data.token); error.config.headers['Authorization'] = 'Bearer ' + res.data.token; return axios(error.config); }); } return Promise.reject(error); });

问题2:多设备登录冲突

解决方案:在AppUser表中增加max_devices字段,登录时检查已绑定设备数:

UPDATE app_user SET device_count = device_count + 1 WHERE user_id = ? AND device_count < max_devices

5. 性能优化与安全加固

5.1 Redis缓存策略优化

移动端用户会话建议采用分级缓存:

# application-redis.yml app: token: cache: base: 1h # 基础缓存时间 active: 7d # 活跃用户延长缓存 max: 30d # 最大缓存时间

实现代码:

public void refreshToken(LoginAppUser user) { // 根据活跃度动态设置缓存时间 long activeTime = userService.getActiveLevel(user.getUserId()); long expireTime = calculateExpire(activeTime); redisCache.setCacheObject( getTokenKey(user.getToken()), user, expireTime, TimeUnit.SECONDS ); }

5.2 安全防护措施

防御手段对比表:

攻击类型防护措施实现方式
暴力破解登录限流Redis计数器+滑动窗口
Token盗用设备指纹请求头中嵌入设备特征码
中间人攻击双向SSL客户端证书校验
数据泄露字段加密JPA属性转换器

设备指纹校验示例:

public boolean checkDeviceFingerprint(HttpServletRequest request) { String clientFingerprint = request.getHeader("X-Device-FP"); String serverFingerprint = buildFingerprint( request.getHeader("User-Agent"), IpUtils.getIpAddr(request), request.getHeader("Accept-Language") ); return serverFingerprint.equals(clientFingerprint); }

这套移动端用户体系已在多个生产环境稳定运行,处理日均百万级请求。实际开发中,建议根据业务需求调整Token刷新策略和设备管理规则。对于高安全要求的场景,可以结合生物识别技术增强认证强度。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询