要在qoder的spring boot项目中添加jwt认证,必须绕过spring security默认表单登录,手动接管token解析与认证上下文注入;需引入jjwt-api、jjwt-impl、jjwt-jackson三个依赖(版本0.11.5),配置base64编码32字节以上密钥,编写jwtutil封装生成/解析/校验逻辑,实现jwtauthenticationfilter注入authentication到securitycontext,并在securityconfig中正确配置过滤器顺序及无状态策略。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜

要在Qoder开发的Spring Boot项目中添加JWT认证,必须绕过Spring Security默认的表单登录流程,手动接管Token解析与认证上下文注入,否则前端携带Bearer Token的请求会直接被拒绝或重定向到登录页。
添加JWT核心依赖
打开pom.xml,在<dependencies></dependencies>中插入以下三项:
<dependency><br> <groupid>io.jsonwebtoken</groupid><br> <artifactid>jjwt-api</artifactid><br> <version>0.11.5</version><br></dependency><br><dependency><br> <groupid>io.jsonwebtoken</groupid><br> <artifactid>jjwt-impl</artifactid><br> <version>0.11.5</version><br> <scope>runtime</scope><br></dependency><br><dependency><br> <groupid>io.jsonwebtoken</groupid><br> <artifactid>jjwt-jackson</artifactid><br> <version>0.11.5</version><br> <scope>runtime</scope><br></dependency>
注意:不能使用0.9.x老版本,它不支持Java 17+的模块化反射机制,运行时会抛NoClassDefFoundError: javax/xml/bind/DatatypeConverter。
配置JWT密钥与参数
在application.yml中新增JWT配置块:
jwt:<br> secret: <strong>【必须是Base64编码的32字节以上随机密钥】</strong><br> expiration: 86400<br> header: Authorization<br> token-prefix: Bearer
生成密钥推荐用命令:openssl rand -base64 32。如果直接写明文字符串(如“mySecretKey”),签名将被轻易伪造,【所有环境都必须用不同密钥】。
编写JwtUtil工具类
创建JwtUtil.java,封装Token生成与解析逻辑:
① 定义generateToken(String username, Map<string object> claims)</string>方法,用Jwts.builder()设置subject、claims、issuedAt、expiration,并调用signWith(SignatureAlgorithm.HS512, secretKey);
② 定义getUsernameFromToken(String token),先去掉Bearer 前缀,再用Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject()提取用户名;
③ 定义validateToken(String token),捕获ExpiredJwtException、UnsupportedJwtException、MalformedJwtException、SignatureException四类异常并返回false,其余情况返回true。
实现自定义认证过滤器
创建JwtAuthenticationFilter.java,继承OncePerRequestFilter:
方法一:重写doFilterInternal,从request.getHeader("Authorization")取值→检查是否以"Bearer "开头→截取token→调用jwtUtil.validateToken()→若通过则解析出username→查库获取UserDetails→构建UsernamePasswordAuthenticationToken→设置SecurityContextHolder.getContext().setAuthentication(authentication)。
方法二:在构造函数中注入AuthenticationManager,但此方式需提前注册DaoAuthenticationProvider,容易与后续密码校验逻辑冲突,不推荐。
这一步漏掉SecurityContextHolder.getContext().setAuthentication(...),后续@PreAuthorize注解永远不生效——因为SecurityContext里根本没放Authentication对象。
配置Spring Security链
创建SecurityConfig.java,标注@Configuration和@EnableWebSecurity:
第一步:声明@Bean返回PasswordEncoder,用BCryptPasswordEncoder而非NoOpPasswordEncoder,后者已废弃且明文存储密码;
第二步:声明@Bean返回AuthenticationManager,调用auth.authenticationManagerBean();
第三步:重写configure(HttpSecurity http),执行http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)→.authorizeHttpRequests(authz -> authz.requestMatchers("/login", "/register", "/actuator/**").permitAll().anyRequest().authenticated())→.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)。
关键点:【addFilterBefore必须放在authorizeHttpRequests之后】,否则过滤器链顺序错乱,Token校验永远不被执行。











