前后台分离使用token
使用场景:前后端分离时(后台使用的是springboot,前端使用的是uniapp),当前台请求登录接口时,后台进行储存用户信息,并生成token,并返回给前端.前端请求其他接口都需要在头部带着token ,才能请求。下面来具体代码说明吧。(对你们有帮助的谢谢点赞收藏,错误的地方也谢谢评论提出,加以改善)
第一步:在pom.xml 文件中引入jar包
<!-- token包--> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency>
第二步:使用工具类JwtUtils.java (这是生成token,和获取token的机制,直接复制可用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | package com.example.changcai.smart_device.tool; import io.jsonwebtoken.Claims; import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.apache.tomcat.util.codec.binary.Base64; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import javax.servlet.http.HttpServletRequest; import java.security.Key; import java.util.Date; import java.util.Map; /** * jwt */ public class JwtUtils { /** * @param claims 自定义的 map * @param ttl 过期时间 * @return */ public static String createToken(Map<String, Object> claims, Long ttl) { Key key = generateKey(); SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; Long nowMillis = System.currentTimeMillis(); JwtBuilder builder = Jwts.builder() .setHeaderParam( "typ" , "JWT" ) .setHeaderParam( "alg" , "HS256" ) .setClaims(claims) .signWith(signatureAlgorithm, key); if (ttl != null && ttl >= 0 ) { Long expMillis = nowMillis + ttl * 1000 ; Date exp = new Date(expMillis); builder.setExpiration(exp); } return builder.compact(); } /** * @param claims 自定义的 map * @return */ public static String createToken(Map<String, Object> claims) { return createToken(claims, null ); } /** * @param jwt 创建的 jwt 字符串 * @return */ public static Claims parse(String jwt) { if (jwt == null ) { return null ; } try { return Jwts.parser() .setSigningKey(generateKey()) .parseClaimsJws(jwt) .getBody(); } catch (Exception e) { return null ; } } /** * @return */ private static SecretKey generateKey() { String stringKey = "changcai" ; byte [] encodedKey = Base64.decodeBase64(stringKey); return new SecretKeySpec(encodedKey, 0 , encodedKey.length, "AES" ); } /** * @return */ public static Integer getParseToken(HttpServletRequest request, String token, String key) { Claims parse = parse(token); if (parse == null ) { return null ; } return (Integer) parse.get(key); } public static Integer getParseToken(String token, String key) { Claims parse = parse(token); if (parse == null ) { return null ; } return (Integer) parse.get(key); } /*public static String getParseTokenStr(HttpServletRequest request, String token, String key) { Claims parse = parse(token); if (parse == null) { return null; } return (String) parse.get(key); }*/ public static Long parseTokenStr(String token, String key) { Claims parse = parse(token); Object uid = parse.get(key); return Long.parseLong(uid.toString()); } public static void main(String[] args) { System.out.println(generateKey()); } } |
第三步:后台登录接口存储token,并返回给前端 该controller 继承一个BaseController
@ApiOperation("用户登录接口Token") @RequestMapping(value = "wechatLoginToken",method = RequestMethod.POST) @ResponseBody public ResultInfo wechatLoginToken(@RequestBody @ApiParam("用户对象") Member member1){ HashMap<String,Object> map=new HashMap(); Member member=memberService.byUserName(member1.getUsername()); if(null==member){ return new ResultInfo(203,"用户不存在!",false); }else{ if("1".equals(member.getIsEnable())){ return new ResultInfo(204,"用户已禁用!",false); }else if("1".equals(member.getIsDeleted())){ return new ResultInfo(204,"用户已删!",false); }else{ if(!member.getPassword().equals(MD5Util.md5(member1.getPassword()))){ return new ResultInfo(203,"用户密码不正确!",false); }else{ //登录成功后 HashMap<String, Object> claims = new HashMap<>(); claims.put("id", member.getId()); //token过期时间24小时 String token = JwtUtils.createToken(claims, 864000L); map.put("token",token); map.put("member",member); return new ResultInfo(200,"用户登录成功!",map); } } } }
第四步:BaseController(主要解析token )
package com.example.changcai.smart_device.controller; import com.example.changcai.smart_device.entity.Member; import com.example.changcai.smart_device.service.MemberService; import com.example.changcai.smart_device.tool.JwtUtils; import com.github.pagehelper.util.StringUtil; import io.jsonwebtoken.Claims; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.ModelAttribute; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Slf4j @Component public class BaseController { @Resource protected HttpServletRequest request; @Resource protected HttpServletResponse response; @Resource private MemberService memberService; protected Member member; @ModelAttribute public Member getMember() { String token = request.getHeader("X-Token"); if (StringUtil.isNotEmpty(token)) { System.out.println("token的值:"+token); Claims parse = JwtUtils.parse(token); Object obj = parse.get("id"); member = memberService.getById(obj.toString()); return member; } return null; } }
测试登录后返回的值
再写一个controller测试类,登录后,传token 获取member 对象
@ApiOperation("通过Token获取用户") @RequestMapping(value = "byTokenGetMember",method = RequestMethod.POST) @ResponseBody public ResultInfo byTokenGetMember(){ return new ResultInfo(200,"用户登录成功!",member); }
测试效果如
注意点1:前端请求其他接口时,都需要把token 带在头部,参数格式是:
headers:{
X-Token:前端登录成功后保存的token值
}
注意点2:如果项目使用到了swagger,请求接口heard头部想显示“X-Token”
代码截图
效果:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!