
目录
JWT是一种用于双方之间传递安全信息的简洁的、URL安全的表述性声明规范。是由用户以用户名、密码登录,服务端验证后,会生成一个 token,返回给客户端,客户端在下次访问的过程中携带这个 token,服务端责每次验证这个token。因为数字签名的存在,这些信息是可信的,JWT可以使用HMAC算法或者是RSA的公私秘钥对进行签名。
在SpringBoot项目下创建config(工具包)包,在包底下创建一下类和枚举。
- package com.alanx.java.util;
-
-
- import com.alanx.java.bean.Users;
- import io.jsonwebtoken.Claims;
- import io.jsonwebtoken.Jws;
- import io.jsonwebtoken.Jwts;
- import io.jsonwebtoken.SignatureAlgorithm;
- import org.springframework.util.StringUtils;
-
- import javax.servlet.http.HttpServletRequest;
- import java.util.Date;
-
-
- public class JwtUtils {
-
- //常量
- public static final long EXPIRE = 1000 * 60 * 60 * 24; //token过期时间
- public static final String APP_SECRET = "13579"; //秘钥,加盐
-
- // @param id 当前用户ID
- // @param issuer 该JWT的签发者,是否使用是可选的
- // @param subject 该JWT所面向的用户,是否使用是可选的
- // @param ttlMillis 什么时候过期,这里是一个Unix时间戳,是否使用是可选的
- // @param audience 接收该JWT的一方,是否使用是可选的
- //生成token字符串的方法
- public static String getJwtToken(Users user) {
-
- String JwtToken = Jwts.builder()
- .setHeaderParam("typ", "JWT") //头部信息
- .setHeaderParam("alg", "HS256") //头部信息
- //下面这部分是payload部分
- // 设置默认标签
- .setSubject("alanx") //设置jwt所面向的用户
- .setIssuedAt(new Date()) //设置签证生效的时间
- .setExpiration(new Date(System.currentTimeMillis() + EXPIRE)) //设置签证失效的时间
- //自定义的信息,这里存储id和姓名信息
- .claim("id", user.getId()) //设置token主体部分 ,存储用户信息
- .claim("name", user.getUserName())
- .claim("nickName",user.getNickName())
- //下面是第三部分
- .signWith(SignatureAlgorithm.HS256, APP_SECRET)
- .compact();
- // 生成的字符串就是jwt信息,这个通常要返回出去
- return JwtToken;
- }
-
- /**
- * 判断token是否存在与有效
- * 直接判断字符串形式的jwt字符串
- *
- * @param jwtToken
- * @return
- */
- public static boolean checkToken(String jwtToken) {
- if (StringUtils.isEmpty(jwtToken)) return false;
- try {
- Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- return true;
- }
-
- /**
- * 判断token是否存在与有效
- * 因为通常jwt都是在请求头中携带,此方法传入的参数是请求
- *
- * @param request
- * @return
- */
- public static boolean checkToken(HttpServletRequest request) {
- try {
- String jwtToken = request.getHeader("token");//注意名字必须为token才能获取到jwt
- if (StringUtils.isEmpty(jwtToken)) return false;
- Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- return true;
- }
-
- /**
- * 根据token字符串获取会员id
- * 这个方法也直接从http的请求中获取id的
- *
- * @param request
- * @return
- */
- public static String getMemberIdByJwtToken(HttpServletRequest request) {
- String jwtToken = request.getHeader("token");
- if (StringUtils.isEmpty(jwtToken)) return "";
- Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
- Claims claims = claimsJws.getBody();
- return (String) claims.get("id");
- }
-
- /**
- * 解析JWT
- *
- * @param jwt
- * @return
- */
- public static Claims parseJWT(String jwt) {
- Claims claims = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwt).getBody();
- return claims;
- }
- }
- package com.alanx.java.util;
-
- import lombok.Data;
-
- import java.io.Serializable;
-
- /**
- * @Description: 统一返回实体
- */
- @Data
- public class JsonResult<T> implements Serializable {
- private Boolean success;
- private Integer errorCode;
- private String errorMsg;
- private T data;
-
- public JsonResult() {
- }
-
- public JsonResult(boolean success) {
- this.success = success;
- this.errorCode = success ? ResultCode.SUCCESS.getCode() : ResultCode.COMMON_FAIL.getCode();
- this.errorMsg = success ? ResultCode.SUCCESS.getMessage() : ResultCode.COMMON_FAIL.getMessage();
- }
-
- public JsonResult(boolean success, ResultCode resultEnum) {
- this.success = success;
- this.errorCode = success ? ResultCode.SUCCESS.getCode() : (resultEnum == null ? ResultCode.COMMON_FAIL.getCode() : resultEnum.getCode());
- this.errorMsg = success ? ResultCode.SUCCESS.getMessage() : (resultEnum == null ? ResultCode.COMMON_FAIL.getMessage() : resultEnum.getMessage());
- }
-
- public JsonResult(boolean success, T data) {
- this.success = success;
- this.errorCode = success ? ResultCode.SUCCESS.getCode() : ResultCode.COMMON_FAIL.getCode();
- this.errorMsg = success ? ResultCode.SUCCESS.getMessage() : ResultCode.COMMON_FAIL.getMessage();
- this.data = data;
- }
-
- public JsonResult(boolean success, ResultCode resultEnum, T data) {
- this.success = success;
- this.errorCode = success ? ResultCode.SUCCESS.getCode() : (resultEnum == null ? ResultCode.COMMON_FAIL.getCode() : resultEnum.getCode());
- this.errorMsg = success ? ResultCode.SUCCESS.getMessage() : (resultEnum == null ? ResultCode.COMMON_FAIL.getMessage() : resultEnum.getMessage());
- this.data = data;
- }
-
- }
- package com.alanx.java.util;
-
- /**
- * @Description: 返回码定义
- * 规定:
- * #1表示成功
- * #1001~1999 区间表示参数错误
- * #2001~2999 区间表示用户错误
- * #3001~3999 区间表示接口异常
- */
- public enum ResultCode {
- /* 成功 */
- SUCCESS(200, "成功"),
-
- /* 默认失败 */
- COMMON_FAIL(999, "失败"),
-
- /* 参数错误:1000~1999 */
- PARAM_NOT_VALID(1001, "参数无效"),
- PARAM_IS_BLANK(1002, "参数为空"),
- PARAM_TYPE_ERROR(1003, "参数类型错误"),
- PARAM_NOT_COMPLETE(1004, "参数缺失"),
-
- /* 用户错误 */
- USER_NOT_LOGIN(2001, "用户未登录"),
- USER_ACCOUNT_EXPIRED(2002, "账号已过期"),
- USER_CREDENTIALS_ERROR(2003, "密码错误"),
- USER_CREDENTIALS_EXPIRED(2004, "密码过期"),
- USER_ACCOUNT_DISABLE(2005, "账号不可用"),
- USER_ACCOUNT_LOCKED(2006, "账号被锁定"),
- USER_ACCOUNT_NOT_EXIST(2007, "账号不存在"),
- USER_ACCOUNT_ALREADY_EXIST(2008, "账号已存在"),
- USER_ACCOUNT_USE_BY_OTHERS(2009, "账号下线"),
-
- /* 业务错误 */
- NO_PERMISSION(3001, "没有权限");
- private Integer code;
- private String message;
-
- ResultCode(Integer code, String message) {
- this.code = code;
- this.message = message;
- }
-
- public Integer getCode() {
- return code;
- }
-
- public void setCode(Integer code) {
- this.code = code;
- }
-
- public String getMessage() {
- return message;
- }
-
- public void setMessage(String message) {
- this.message = message;
- }
-
- /**
- * 根据code获取message
- *
- * @param code
- * @return
- */
- public static String getMessageByCode(Integer code) {
- for (ResultCode ele : values()) {
- if (ele.getCode().equals(code)) {
- return ele.getMessage();
- }
- }
- return null;
- }
- }
- package com.alanx.java.util;
-
-
- /**
- * @Description: 返回体构造工具
- */
- public class ResultTool {
- public static JsonResult success() {
- return new JsonResult(true);
- }
-
- public static <T> JsonResult<T> success(T data) {
- return new JsonResult(true, data);
- }
-
- public static JsonResult fail() {
- return new JsonResult(false);
- }
-
- public static JsonResult fail(ResultCode resultEnum) {
- return new JsonResult(false, resultEnum);
- }
- }
首次登录成功后,将信息存放到Rides中
- package com.alanx.java.controller;
-
- import com.alanx.java.bean.Users;
- import com.alanx.java.service.UserService;
- import com.alanx.java.util.JsonResult;
- import com.alanx.java.util.JwtUtils;
- import com.alanx.java.util.ResultTool;
- import com.alibaba.fastjson.JSON;
- import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
- import org.springframework.data.redis.core.StringRedisTemplate;
- import org.springframework.web.bind.annotation.PostMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
-
- import javax.annotation.Resource;
- import java.util.List;
- import java.util.concurrent.TimeUnit;
-
- @RestController
- @RequestMapping("/users")
- public class UsersController {
- @Resource
- private UserService service;
- @Resource
- private StringRedisTemplate stringRedisTemplate;
-
- @PostMapping("/login")
- public String login(Users users) {
- QueryWrapper<Users> wrapper = new QueryWrapper<>();
- wrapper.eq("username", users.getUserName());
- wrapper.eq("password", users.getPassWord());
- List<Users> list = service.list(wrapper);
- if (list.size() == 0) {
- return JSON.toJSONString(ResultTool.fail()); //失败了返回一个错误代码
- }
- Users u = list.get(0);
- String token = JwtUtils.getJwtToken(u);
- stringRedisTemplate.opsForValue().set(u.getId() + "", token, 1, TimeUnit.DAYS); //存放到redis中
- JsonResult<String> result = ResultTool.success(token);
- return JSON.toJSONString(result);
- }
- }
使用Postman测试一下结果密码错误会返回一个错误代码

密码正确的话,会出现jwt

在Redis中查询结果,复制结果去JWT官网进行解码后就会出现除密码外的信息。


在第二部分载体中可以自定义解码出来的结果,在JwtUtils类中的getJwtToken方法中加入信息

