JWT认证原理与Java Web实战指南
1. 登录认证技术选型与JWT原理剖析在Java Web开发中用户认证是系统安全的第一道防线。传统session认证方式在分布式环境下会面临会话共享问题而JWT(JSON Web Token)作为一种无状态的认证机制完美解决了这一痛点。我最近在重构一个电商后台时就采用了JWTFilter的方案实测下来比传统方案节省了40%的认证相关代码量。JWT由三部分组成通过点号连接Header声明类型和加密算法如HS256Payload存放有效信息用户ID、过期时间等Signature对前两部分的签名防止篡改一个典型的JWT令牌看起来像这样eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c关键点选择HS256而非RS256算法时务必保证密钥长度≥32字符。我曾因使用简单密钥导致测试环境被爆破教训深刻。2. JWT实战开发全流程2.1 依赖配置与工具类封装使用JJWT库实现JWT时首先在pom.xml添加依赖dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt-api/artifactId version0.11.5/version /dependency dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt-impl/artifactId version0.11.5/version scoperuntime/scope /dependency然后封装JwtUtil工具类核心方法包括public class JwtUtil { private static final String SECRET_KEY your-256-bit-secret; private static final long EXPIRATION 86400000; // 24小时 public static String generateToken(UserDetails user) { return Jwts.builder() .setSubject(user.getUsername()) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() EXPIRATION)) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); } public static boolean validateToken(String token) { try { Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token); return true; } catch (Exception e) { // 记录异常日志 return false; } } }2.2 登录接口实现在AuthController中处理登录逻辑PostMapping(/login) public ResponseEntity? login(RequestBody LoginRequest request) { // 1. 验证用户名密码 UserDetails user userService.loadUserByUsername(request.getUsername()); if(!passwordEncoder.matches(request.getPassword(), user.getPassword())) { throw new BadCredentialsException(密码错误); } // 2. 生成JWT String token JwtUtil.generateToken(user); // 3. 返回响应 return ResponseEntity.ok() .header(HttpHeaders.AUTHORIZATION, Bearer token) .body(Map.of( username, user.getUsername(), roles, user.getAuthorities() )); }避坑指南永远不要在JWT中存储敏感信息如密码。我曾见过有开发者把用户权限列表直接放在Payload里导致越权漏洞。3. Filter实现认证拦截3.1 自定义JwtFilter继承OncePerRequestFilter实现认证过滤器public class JwtAuthenticationFilter extends OncePerRequestFilter { Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { // 1. 从Header提取token String header request.getHeader(Authorization); if (header null || !header.startsWith(Bearer )) { chain.doFilter(request, response); return; } String token header.substring(7); // 2. 验证token有效性 if (!JwtUtil.validateToken(token)) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED); return; } // 3. 解析用户信息并设置认证上下文 String username JwtUtil.extractUsername(token); UserDetails user userService.loadUserByUsername(username); UsernamePasswordAuthenticationToken authentication new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities()); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authentication); chain.doFilter(request, response); } }3.2 Filter注册配置在Spring Security配置类中添加Configuration EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) .authorizeRequests() .antMatchers(/api/auth/**).permitAll() .anyRequest().authenticated(); } }4. 安全加固与性能优化4.1 防御常见攻击手段攻击类型防御措施实现示例CSRF禁用Cookiehttp.csrf().disable()XSS响应头过滤response.setHeader(X-XSS-Protection, 1; modeblock)重放攻击JWT过期时间JwtUtil.EXPIRATION 180000030分钟暴力破解登录限流RateLimiter(value 5, timeout 1)4.2 令牌刷新机制当JWT临近过期时前端应调用刷新接口获取新tokenPostMapping(/refresh) public ResponseEntity? refreshToken(RequestHeader(Authorization) String oldToken) { if (!JwtUtil.canRefresh(oldToken)) { throw new InvalidTokenException(令牌不可刷新); } String username JwtUtil.extractUsername(oldToken); UserDetails user userService.loadUserByUsername(username); String newToken JwtUtil.generateToken(user); return ResponseEntity.ok() .header(HttpHeaders.AUTHORIZATION, Bearer newToken) .build(); }在JwtUtil中添加判断逻辑public static boolean canRefresh(String token) { Date expiration extractExpiration(token); return expiration.after(new Date(System.currentTimeMillis() - 300000)); // 过期前5分钟可刷新 }5. 生产环境问题排查实录5.1 跨域问题处理当遇到跨域请求被拦截时需配置CORSBean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource(); CorsConfiguration config new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOriginPattern(*); config.addAllowedHeader(*); config.addAllowedMethod(*); source.registerCorsConfiguration(/**, config); return new CorsFilter(source); }5.2 性能监控要点使用Spring Actuator监控认证性能management: endpoints: web: exposure: include: health,metrics,httptrace metrics: tags: application: ${spring.application.name}关键指标监控项http.server.requests认证接口响应时间spring.security.authentication.success认证成功次数jvm.memory.usedJWT缓存内存占用6. 前后端协作规范6.1 接口约定示例登录成功响应{ code: 200, data: { username: admin, roles: [ROLE_ADMIN], access_token: eyJhbGci..., expires_in: 86400 } }认证失败响应{ code: 401, message: 无效的认证令牌, timestamp: 2023-07-20T08:30:15Z }6.2 前端存储方案Vue项目推荐使用vuex-persistedstate// store.js import createPersistedState from vuex-persistedstate export default new Vuex.Store({ plugins: [createPersistedState({ storage: window.sessionStorage, key: auth })], state: { token: null, user: null } })React项目可采用redux-persist// store.js import { persistStore, persistReducer } from redux-persist import storage from redux-persist/lib/storage const persistConfig { key: root, storage, } const persistedReducer persistReducer(persistConfig, rootReducer) const store createStore(persistedReducer) const persistor persistStore(store)7. 扩展思考微服务场景下的JWT实践在微服务架构中JWT需要额外考虑令牌传播通过Feign拦截器自动传递JWTpublic class FeignRequestInterceptor implements RequestInterceptor { Override public void apply(RequestTemplate template) { String token SecurityContextHolder.getContext().getAuthentication().getCredentials().toString(); template.header(Authorization, Bearer token); } }权限继承在Gateway层验证基础权限各服务验证业务权限黑名单处理使用Redis存储失效令牌Repository public class TokenBlacklist { private final RedisTemplateString, String redisTemplate; public void addToBlacklist(String token, long expiration) { redisTemplate.opsForValue().set( blacklist: token, 1, expiration - System.currentTimeMillis(), TimeUnit.MILLISECONDS ); } public boolean isBlacklisted(String token) { return redisTemplate.hasKey(blacklist: token); } }在JwtFilter中增加检查if (tokenBlacklist.isBlacklisted(token)) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, 令牌已失效); return; }

相关新闻

多智能体协作的“通用语“:MCP + A2A 协议栈实战解析

多智能体协作的“通用语“:MCP + A2A 协议栈实战解析

多智能体协作的"通用语":MCP A2A 协议栈实战解析 ![多智能体协作](https://picsum.photos/seed/17860690546182/800/400) 2026 年,大模型竞争的主战场正在从"单模型能力"转向"多智能体协作"。当中国日均词元调用量突破 1…

2026/8/7 14:09:41 阅读更多 →
fastBPE在Mac OSX上的安装与配置:解决编译难题的实用技巧

fastBPE在Mac OSX上的安装与配置:解决编译难题的实用技巧

fastBPE在Mac OSX上的安装与配置:解决编译难题的实用技巧 【免费下载链接】fastBPE Fast BPE 项目地址: https://gitcode.com/gh_mirrors/fa/fastBPE fastBPE是一款高效的C实现的子词单元处理工具,广泛应用于神经机器翻译中稀有词处理场景。本文将…

2026/8/7 14:08:41 阅读更多 →
AM与FM调制解调原理详解:从载波到信号的工程实践

AM与FM调制解调原理详解:从载波到信号的工程实践

1. 从“载波”到“信息”:模拟调制的核心逻辑 如果你拆开一台老式收音机,或者观察过早期的对讲机电路板,会发现一个有趣的现象:它们处理声音信号的方式,和我们今天熟悉的数字设备截然不同。我们今天要聊的AM&#xff0…

2026/8/7 14:08:41 阅读更多 →

最新新闻

深度解析Shizuku:解锁Android非root设备系统级权限的终极指南

深度解析Shizuku:解锁Android非root设备系统级权限的终极指南

深度解析Shizuku:解锁Android非root设备系统级权限的终极指南 【免费下载链接】awesome-shizuku Curated list of awesome Android apps making use of Shizuku 项目地址: https://gitcode.com/gh_mirrors/aw/awesome-shizuku 你是否曾因Android系统的权限限…

2026/8/7 15:00:14 阅读更多 →
JPlag:学术诚信守护者,智能代码抄袭检测的终极解决方案

JPlag:学术诚信守护者,智能代码抄袭检测的终极解决方案

JPlag:学术诚信守护者,智能代码抄袭检测的终极解决方案 【免费下载链接】JPlag State-of-the-Art Source Code Plagiarism & Collusion Detection. Check for plagiarism in a set of programs. 项目地址: https://gitcode.com/gh_mirrors/jp/JPla…

2026/8/7 15:00:14 阅读更多 →
aardio与Python进程通信实现桌面端图像处理:管道通信与Base64数据交换详解

aardio与Python进程通信实现桌面端图像处理:管道通信与Base64数据交换详解

1. 项目概述:为什么要在 aardio 里调用 Python 处理图片? 如果你是一个桌面应用开发者,尤其是用 aardio 这种专注于 Windows 桌面快速开发的工具,你可能会遇到一个经典难题:aardio 自带的图形处理功能,对于…

2026/8/7 15:00:14 阅读更多 →
Avalonia跨平台开发环境配置全攻略:从.NET SDK到IDE实战

Avalonia跨平台开发环境配置全攻略:从.NET SDK到IDE实战

1. 项目概述:为什么是Avalonia? 如果你是从WPF、WinForms或者UWP过来的开发者,第一次听说Avalonia,可能会有点懵。简单来说,Avalonia是一个开源的、跨平台的.NET UI框架。它的目标很明确:让你能用熟悉的XA…

2026/8/7 15:00:14 阅读更多 →
VOS 8.05软交换平台源码编译与部署实战指南

VOS 8.05软交换平台源码编译与部署实战指南

1. 项目概述:从零构建一个企业级语音通信系统 最近在帮一个朋友的公司折腾他们的电话系统,他们之前用的老式PBX设备维护成本高、功能扩展困难,想换一套基于IP的现代化方案。聊了一圈,发现很多中小企业在语音通信这块都面临类似的痛…

2026/8/7 15:00:13 阅读更多 →
Element UI弹窗全屏化实战:从原理到避坑的完整解决方案

Element UI弹窗全屏化实战:从原理到避坑的完整解决方案

1. 项目缘起:一个看似简单却暗藏玄机的需求 最近在重构一个后台管理系统时,遇到了一个产品经理提出的“小需求”:希望某个数据量巨大的报表预览弹窗能支持全屏查看,方便用户更专注地分析数据。这个需求听起来合情合理,…

2026/8/7 14:59:13 阅读更多 →

日新闻

为什么scrcpy成为Android投屏的终极解决方案:完整实战指南

为什么scrcpy成为Android投屏的终极解决方案:完整实战指南

为什么scrcpy成为Android投屏的终极解决方案:完整实战指南 【免费下载链接】scrcpy Display and control your Android device 项目地址: https://gitcode.com/GitHub_Trending/sc/scrcpy 想要将Android手机屏幕完美投射到电脑上,享受大屏操作的自…

2026/8/7 0:00:19 阅读更多 →
如何在5分钟内掌握Tom Select:打造现代化表单选择器的终极指南

如何在5分钟内掌握Tom Select:打造现代化表单选择器的终极指南

如何在5分钟内掌握Tom Select:打造现代化表单选择器的终极指南 【免费下载链接】tom-select Tom Select is a lightweight (~16kb gzipped) hybrid of a textbox and select box. Forked from selectize.js to provide a framework agnostic autocomplete widget wi…

2026/8/7 0:00:19 阅读更多 →
5分钟快速上手:NSZ压缩工具终极指南,轻松管理Switch游戏文件

5分钟快速上手:NSZ压缩工具终极指南,轻松管理Switch游戏文件

5分钟快速上手:NSZ压缩工具终极指南,轻松管理Switch游戏文件 【免费下载链接】nsz NSZ - Homebrew compatible NSP/XCI compressor/decompressor 项目地址: https://gitcode.com/gh_mirrors/ns/nsz 你是否在为Nintendo Switch游戏文件占用大量存储…

2026/8/7 0:00:19 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/6 22:02:27 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/6 22:02:27 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/6 22:02:27 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/5 23:28:39 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/6 22:02:28 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/5 23:46:51 阅读更多 →