SpringBoot 集成 JWT 实现登录认证 + 权限拦截(电商系统实战,代码可直接复制)
一、开篇引言做前后端分离的电商管理系统登录认证与权限控制是绝对的核心功能也是 Java 后端面试的高频考点。你是不是也遇到过这些问题前后端分离项目Session 共享困难无法用传统 Session 做登录认证不知道如何实现无状态的用户登录接口安全无法保障分不清 JWT 的原理、结构踩坑后无法排查问题不知道如何结合 SpringBoot 实现登录拦截、权限校验防止未授权访问本文结合你正在做的电商管理系统从原理到实战完整实现 SpringBoot 集成 JWT 实现登录认证 全局权限拦截包含完整可复制代码、高频踩坑总结15 分钟就能搭建企业级登录认证体系完美适配你的项目。本文基于 SpringBoot 2.7.x JWT 0.11.5适合 Java 后端初学者、正在做前后端分离项目的同学尤其适合大二计算机专业学生练手电商项目。二、核心知识点先懂原理再写代码1. JWT 核心原理JWTJSON Web Token是一种无状态的身份认证方案核心是将用户身份信息加密后生成 Token前端存储 Token每次请求携带 Token 到后端后端解密验证身份无需在服务端存储 Session完美适配前后端分离项目。2. JWT 结构拆解JWT 由 3 部分组成用 . 分隔Header头部存储签名算法如 HS256、Token 类型Payload载荷存储用户信息如用户 ID、用户名、过期时间等自定义声明Signature签名用密钥对 HeaderPayload 加密生成防止 Token 被篡改3. 核心优势无状态服务端无需存储 Session扩展性强适合分布式系统跨域友好完美适配前后端分离、移动端等场景安全性高签名机制防止 Token 被篡改可设置过期时间保障安全三、环境准备直接复制无需修改!--SpringBootWeb核心依赖--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency!--JWT核心依赖0.11.5稳定版--dependencygroupIdio.jsonwebtoken/groupIdartifactIdjjwt-api/artifactIdversion0.11.5/version/dependencydependencygroupIdio.jsonwebtoken/groupIdartifactIdjjwt-impl/artifactIdversion0.11.5/versionscoperuntime/scope/dependencydependencygroupIdio.jsonwebtoken/groupIdartifactIdjjwt-jackson/artifactIdversion0.11.5/versionscoperuntime/scope/dependency!--MyBatis-Plus复用电商系统已有依赖--dependencygroupIdcom.baomidou/groupIdartifactIdmybatis-plus-boot-starter/artifactIdversion3.5.3/version/dependency!--Lombok简化代码--dependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependency2. application.yml 配置#JWT配置 jwt:# 密钥生产环境请更换为复杂密钥建议16位以上 secret:my-secret-key-1234567890# 过期时间单位毫秒7天7*24*60*60*1000604800000 expiration:604800000#Token前缀 token-prefix:Bearer# 请求头名称 header:Authorization四、核心代码实现严格拆分「工具类 拦截器 接口」4.1 JWT 工具类核心生成 / 解析 Tokenpackagecom.example.demo.utils;importio.jsonwebtoken.Claims;importio.jsonwebtoken.Jwts;importio.jsonwebtoken.SignatureAlgorithm;importio.jsonwebtoken.security.Keys;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.stereotype.Component;importjavax.crypto.SecretKey;importjava.nio.charset.StandardCharsets;importjava.util.Date;importjava.util.HashMap;importjava.util.Map;/** * JWT 工具类 * 用于生成 Token、解析 Token、验证 Token 有效性 */ComponentpublicclassJwtUtils{Value(${jwt.secret})privateStringsecret;Value(${jwt.expiration})privateLongexpiration;Value(${jwt.token-prefix})privateStringtokenPrefix;/** * 生成密钥 */privateSecretKeygetSignKey(){returnKeys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));}/** * 生成 Token * param userId 用户ID * param username 用户名 * return 生成的 Token */publicStringgenerateToken(LonguserId,Stringusername){MapString,ObjectclaimsnewHashMap();claims.put(userId,userId);claims.put(username,username);returncreateToken(claims,username);}/** * 创建 Token */privateStringcreateToken(MapString,Objectclaims,Stringsubject){DatenownewDate();DateexpireDatenewDate(now.getTime()expiration);returnJwts.builder().setClaims(claims)// 自定义载荷.setSubject(subject)// 主题.setIssuedAt(now)// 签发时间.setExpiration(expireDate)// 过期时间.signWith(getSignKey(),SignatureAlgorithm.HS256)// 签名.compact();}/** * 解析 Token获取载荷 */publicClaimsparseToken(Stringtoken){returnJwts.parserBuilder().setSigningKey(getSignKey()).build().parseClaimsJws(token).getBody();}/** * 从 Token 中获取用户ID */publicLonggetUserIdFromToken(Stringtoken){ClaimsclaimsparseToken(token);returnLong.valueOf(claims.get(userId).toString());}/** * 验证 Token 是否过期 */publicBooleanisTokenExpired(Stringtoken){ClaimsclaimsparseToken(token);returnclaims.getExpiration().before(newDate());}/** * 验证 Token 有效性 */publicBooleanvalidateToken(Stringtoken){try{return!isTokenExpired(token);}catch(Exceptione){returnfalse;}}/** * 去除 Token 前缀 */publicStringremovePrefix(Stringtoken){if(token.startsWith(tokenPrefix)){returntoken.substring(tokenPrefix.length()).trim();}returntoken;}}4.2 JWT 拦截器全局权限拦截验证 Tokenpackagecom.example.demo.interceptor;importcom.example.demo.utils.JwtUtils;importorg.springframework.stereotype.Component;importorg.springframework.web.servlet.HandlerInterceptor;importjavax.annotation.Resource;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;/** * JWT 拦截器 * 拦截所有请求验证 Token 有效性实现登录认证 */ComponentpublicclassJwtInterceptorimplementsHandlerInterceptor{ResourceprivateJwtUtilsjwtUtils;OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{// 1. 处理跨域预检请求OPTIONS 直接放行if(OPTIONS.equals(request.getMethod())){returntrue;}// 2. 从请求头获取 TokenStringtokenrequest.getHeader(Authorization);// 3. Token 为空返回未授权if(tokennull||token.isEmpty()){response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);response.getWriter().write({\code\:401,\msg\:\未登录请先登录\});returnfalse;}// 4. 去除 Token 前缀tokenjwtUtils.removePrefix(token);// 5. 验证 Token 有效性if(!jwtUtils.validateToken(token)){response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);response.getWriter().write({\code\:401,\msg\:\Token 已过期请重新登录\});returnfalse;}// 6. Token 有效放行请求returntrue;}}4.3 拦截器配置类注册拦截器配置放行路径packagecom.example.demo.config;importcom.example.demo.interceptor.JwtInterceptor;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.servlet.config.annotation.InterceptorRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;importjavax.annotation.Resource;/** * WebMvc 配置类 * 注册 JWT 拦截器配置拦截/放行路径 */ConfigurationpublicclassWebMvcConfigimplementsWebMvcConfigurer{ResourceprivateJwtInterceptorjwtInterceptor;OverridepublicvoidaddInterceptors(InterceptorRegistryregistry){registry.addInterceptor(jwtInterceptor)// 拦截所有请求.addPathPatterns(/**)// 放行登录、注册等接口电商系统核心放行路径.excludePathPatterns(/user/login,// 登录接口/user/register,// 注册接口/captcha/get,// 验证码接口/doc.html,// Knife4j 接口文档/webjars/**,/v3/api-docs/**);}}4.4 登录接口实现电商系统用户登录packagecom.example.demo.controller;importcom.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;importcom.example.demo.common.Result;importcom.example.demo.entity.User;importcom.example.demo.service.UserService;importcom.example.demo.utils.JwtUtils;importorg.springframework.util.DigestUtils;importorg.springframework.web.bind.annotation.PostMapping;importorg.springframework.web.bind.annotation.RequestBody;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;importjavax.annotation.Resource;importjava.util.HashMap;importjava.util.Map;/** * 用户登录控制器 * 实现电商系统用户登录生成 JWT Token */RestControllerRequestMapping(/user)publicclassLoginController{ResourceprivateUserServiceuserService;ResourceprivateJwtUtilsjwtUtils;/** * 用户登录接口 * param user 登录信息username、password * return 登录结果 Token */PostMapping(/login)publicResultMapString,Objectlogin(RequestBodyUseruser){// 1. 校验用户名密码非空if(user.getUsername()null||user.getPassword()null){returnResult.fail(用户名或密码不能为空);}// 2. 根据用户名查询用户LambdaQueryWrapperUserwrappernewLambdaQueryWrapper();wrapper.eq(User::getUsername,user.getUsername()).eq(User::getDeleted,0);UserexistUseruserService.getOne(wrapper);// 3. 用户不存在if(existUsernull){returnResult.fail(用户名不存在);}// 4. 密码校验实际项目用 BCrypt 加密此处用 MD5 演示StringinputPwdDigestUtils.md5DigestAsHex(user.getPassword().getBytes());if(!inputPwd.equals(existUser.getPassword())){returnResult.fail(密码错误);}// 5. 生成 JWT TokenStringtokenjwtUtils.generateToken(existUser.getId(),existUser.getUsername());// 6. 返回登录结果MapString,ObjectresultnewHashMap();result.put(token,token);result.put(user,existUser);returnResult.success(result);}}五、接口测试效果演示1. 登录请求请求POST /user/login请求体{username:zhangsan,password:123456}返回{code:200,msg:操作成功,data:{token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...,user:{id:1,username:zhangsan,nickname:张三,status:1}}}2. 带 Token 请求用户接口请求头Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…请求GET /user/1返回{code:200,msg:操作成功,data:{id:1,username:zhangsan,nickname:张三}}3. 无 Token / 过期 Token 请求返回{code:401,msg:未登录请先登录}六、高频踩坑总结新手必看坑 1跨域预检请求OPTIONS被拦截原因拦截器没有放行 OPTIONS 请求导致跨域失败解决方案在拦截器中添加 if (“OPTIONS”.equals(request.getMethod())) { return true; }直接放行预检请求坑 2Token 过期时间设置不合理原因过期时间太短用户频繁登录太长安全性低解决方案电商系统建议设置 7 天过期同时实现 Token 刷新机制后续可扩展坑 3密钥泄露Token 被篡改原因密钥过于简单生产环境硬编码在代码中解决方案密钥设置为 16 位以上复杂字符串生产环境通过配置中心管理禁止硬编码坑 4载荷存储敏感信息原因JWT 载荷是 Base64 编码可直接解码不能存储密码等敏感信息解决方案载荷仅存储用户 ID、用户名等非敏感信息敏感信息绝对不能存入坑 5拦截器放行路径配置错误原因登录、验证码等接口被拦截导致无法登录解决方案严格配置放行路径确保登录、注册、验证码等接口不受拦截七、总结与延伸本文完整实现了 SpringBoot 集成 JWT 实现登录认证 全局权限拦截完美适配电商管理系统的登录需求所有代码可直接复制到你的项目中使用。通过本文的实现你可以彻底解决前后端分离项目的登录认证问题实现无状态身份校验掌握 JWT 的核心原理与实战用法应对面试高频考点搭建企业级登录认证体系保障接口安全为后续权限控制RBAC、角色管理打下基础本文是电商管理系统实战系列的第 4 篇上一篇讲解了 MyBatis-Plus 条件查询避坑下一篇将讲解 SpringBoot 集成 Redis 实现缓存优化感兴趣的同学可以关注我持续更新 Java 后端实战内容。八、互动引导你在集成 JWT 时还遇到过哪些问题欢迎在评论区留言我会逐一解答觉得有用的同学点赞 收藏不迷路后续更新更多 Java 后端学习、项目实战、面试技巧关注我持续分享 Java 后端干货陪你从大二到秋招拿 offer
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2512513.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!