货运搬家小程序从0到1(五):JWT 鉴权,拦截器 + ThreadLocal 用户上下文

上篇登录跑通,拿到了 token。这篇解决"token 发出去之后怎么用":拦截器统一验签,业务代码零感知地拿到当前用户。

为什么不用 Spring Security

我的场景:两种角色(USER/DRIVER/ADMIN)、几十个接口、无 OAuth 无 SSO。Spring Security 的过滤器链、SecurityContext、UserDetailsService 那一套,学习成本远超收益。手写一个 JWT 工具 + 一个 MVC 拦截器,总代码不到 200 行 ,每一行都看得懂、改得动。小项目的安全感来自简单,不是来自重量级框架。

三件套:JwtUtil、AuthContext、拦截器

1. JwtUtil:手写 HS256

JWT 结构是 header.payload.signature,HS256 的签名就是 HMAC-SHA256(header + "." + payload, secret)。不引第三方库也能写:

java 复制代码
public static String create(Long userId, String role) {
    String header  = base64("{\"alg\":\"HS256\",\"typ\":\"JWT\"}");
    String payload = base64("{\"uid\":" + userId + ",\"role\":\"" + role
                          + "\",\"exp\":" + (System.currentTimeMillis()/1000 + 7*86400) + "}");
    String sign = hmacSha256(header + "." + payload, SECRET);
    return header + "." + payload + "." + sign;
}

解析时先验签再取 uid/role,过期抛异常。就这么多,没有魔法。

2. AuthContext:ThreadLocal 存当前用户

java 复制代码
public class AuthContext {
    private static final ThreadLocal<Long> UID = new ThreadLocal<>();
    public static void set(Long uid) { UID.set(uid); }
    public static Long uid() { return UID.get(); }
    public static void clear() { UID.remove(); }   // 关键!
}

3. 拦截器:验签 + 放行名单

java 复制代码
public class AuthInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object h) {
        String token = req.getHeader("Authorization");   // "Bearer eyJ..."
        Long uid = JwtUtil.parseUserId(token.replace("Bearer ", ""));
        if (uid == null) { resp.setStatus(401); return false; }
        AuthContext.set(uid);
        return true;
    }
    public void afterCompletion(...) { AuthContext.clear(); }
}

注册时排除公开接口(/api/auth/**/api/vehicle-types、管理端登录等)。

之后所有 Controller 写起来非常干净:

java 复制代码
@GetMapping("/api/me")
public Result me() {
    return Result.ok(userService.info(AuthContext.uid()));  // 当前用户直接拿
}

三个必踩的坑,提前避开

  1. ThreadLocal 必须 remove :Tomcat 线程是复用的,不清理会串用户------这是隐蔽性最高的线上事故来源。放 afterCompletion 里最保险
  2. 放行名单别用通配符放开整个 /api:宁可逐个加白名单
  3. 过期策略从简:7 天过期 + 过期重登。token 自动续期(refresh token)第一版不需要,别给自己加戏

本篇成果

全站鉴权闭环:前端请求头自动带 token → 拦截器验签 → 业务代码 AuthContext.uid() 直取当前用户。下一篇写整个系统的心脏:订单状态机与下单支付。


相关推荐
白远山7 小时前
家政服务家政社区派单实战:调度系统架构设计与实现指南
java·开发语言·小程序·架构·需求分析
微擎应用市场11 小时前
心灵馆咨询系统小程序:一站式心理咨询服务解决方案
小程序
2501_9159184112 小时前
怎么把 Python 写的 Flet 应用打包成 iOS App 并上架 App Store?
android·ios·小程序·https·uni-app·iphone·webview
Geek_Vison12 小时前
小程序容器如何抹平系统差异,让一个小程序运行在 iOS、安卓、鸿蒙和电脑端
小程序·uni-app·harmonyos·mpaas
2601_9499506317 小时前
练题簿:把备考资料装进小程序,随时开启高效在线刷题
人工智能·小程序·刷题·练习·小程序推荐
飞梦工作室17 小时前
H5页面能否直接播放视频号直播?实战方案与踩坑总结
微信小程序·小程序
河南花仙子科技1 天前
企业定制小游戏助力品牌软性传播
大数据·科技·游戏·小程序
StevenLdh1 天前
情绪小恐龙:一个微信小程序从架构设计到部署上线的全记录
微信小程序·小程序·notepad++
m0_587383001 天前
折扣卡CPS软件开发实战:从系统架构设计到上线指南
java·小程序·架构·需求分析
mykj15511 天前
赛事报名小程序系统:一站式解决赛事管理难题
小程序·app开发·体育赛事报名小程序·赛事app