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/10/19 12:28:46 阅读更多 →
fastBPE在Mac OSX上的安装与配置:解决编译难题的实用技巧

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

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

2026/10/19 13:17:11 阅读更多 →
AM与FM调制解调原理详解:从载波到信号的工程实践

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

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

2026/10/19 22:23:36 阅读更多 →

最新新闻

2026年教育培训SaaS系统怎么选?从评价维度到避坑指南全解析

2026年教育培训SaaS系统怎么选?从评价维度到避坑指南全解析

第一次被培训机构老板问“哪家SaaS系统排名高”的时候,我记得很清楚,那是2018年,一个做少儿艺术培训的朋友拿着三份报价单来找我对比。那时候大家比的还是谁家的功能模块多、谁家的App长得好看。到了2026年,这个问题不但没变简单&…

2026/10/20 12:06:01 阅读更多 →
KECA核熵成分分析:训练测试集分离与数据泄漏避坑实践

KECA核熵成分分析:训练测试集分离与数据泄漏避坑实践

简介:这是一份面向非线性高维数据降维的KECA(核熵成分分析)MATLAB程序,适用于机器学习、模式识别及特征提取场景,尤其针对Q9A等需要核熵分析的实验问题。KECA结合核方法与熵理论,将数据映射到高维特征空间后…

2026/10/20 12:06:01 阅读更多 →
Kafka 2.8.0生产者消费者原生实现与高可用配置详解

Kafka 2.8.0生产者消费者原生实现与高可用配置详解

1. 项目概述:为什么一个“简单实现”值得花时间深挖?Kafka集群(2.8.0版本)之四:Java简单实现生产者和消费者——这个标题看起来平平无奇,甚至有点“教科书感”。但在我过去十年带团队落地消息中间件的实战中…

2026/10/20 12:06:01 阅读更多 →
MATLAB数据分析与挖掘实战:数据预处理、特征工程与建模避坑指南

MATLAB数据分析与挖掘实战:数据预处理、特征工程与建模避坑指南

简介:MATLAB数据分析与挖掘实战完整教程整合了配套源码、说明文档与真实数据集,面向工科生、数学专业及算法方向学习者,可系统演练数据导入、清洗、建模、评估与结果分析的完整链路,帮助理解数据挖掘中常用的预处理思路和建模方法…

2026/10/20 12:06:01 阅读更多 →
无GPU也能跑大模型:银河麒麟V10离线部署DeepSeek-R1全流程

无GPU也能跑大模型:银河麒麟V10离线部署DeepSeek-R1全流程

简介:面向银河麒麟V10操作系统技术人员的一份DeepSeek离线部署操作指南,重点解决在内网或无互联网环境下安装ollama大语言模型服务及chatbox客户端的问题。资源为单个docx文档,约2.69MB,内容涵盖系统环境与硬件检查、ollama解压安…

2026/10/20 12:06:01 阅读更多 →
KSyntaxHighlighting编译指南:解决KF6依赖与CMake构建链问题

KSyntaxHighlighting编译指南:解决KF6依赖与CMake构建链问题

1. 项目概述:为什么一个语法高亮库的编译会卡住你一整天?“编译 KSyntaxHighlighting 的过程中遇到的一些问题”——这个标题看起来平平无奇,甚至有点枯燥,但它背后藏着的是无数 C 跨平台开发者的共同记忆:一个看似轻量…

2026/10/20 12:05:01 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →