素材巴巴 > 程序开发 >

JWT登录验证

程序开发 2023-09-05 22:10:12


目录

一、JWT是什么?

1.概念

2.结构

二、书写工具(config)包

1.JwtUtils

2.JsonResult

3.ResultCode

4.ResultTool

三、Controller层


一、JWT是什么?

1.概念

JWT是一种用于双方之间传递安全信息的简洁的、URL安全的表述性声明规范。是由用户以用户名、密码登录,服务端验证后,会生成一个 token,返回给客户端,客户端在下次访问的过程中携带这个 token,服务端责每次验证这个token。因为数字签名的存在,这些信息是可信的,JWT可以使用HMAC算法或者是RSA的公私秘钥对进行签名。

2.结构

二、书写工具(config)包

在SpringBoot项目下创建config(工具包)包,在包底下创建一下类和枚举。

1.JwtUtils

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才能获取到jwtif (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 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;}
 }
 

2.JsonResult

package com.alanx.java.util;import lombok.Data;import java.io.Serializable;/*** @Description: 统一返回实体*/
 @Data
 public class JsonResult 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;}}
 

3.ResultCode

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;}
 }
 

4.ResultTool

package com.alanx.java.util;/*** @Description: 返回体构造工具*/
 public class ResultTool {public static JsonResult success() {return new JsonResult(true);}public static  JsonResult 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);}
 }
 

三、Controller层

首次登录成功后,将信息存放到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 {@Resourceprivate UserService service;@Resourceprivate StringRedisTemplate stringRedisTemplate;@PostMapping("/login")public String login(Users users) {QueryWrapper wrapper = new QueryWrapper<>();wrapper.eq("username", users.getUserName());wrapper.eq("password", users.getPassWord());List 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 result = ResultTool.success(token);return JSON.toJSONString(result);}
 }
 

 使用Postman测试一下结果密码错误会返回一个错误代码

密码正确的话,会出现jwt

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

 

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



标签:

上一篇: angular-cli建立项目 下一篇:
素材巴巴 Copyright © 2013-2021 http://www.sucaibaba.com/. Some Rights Reserved. 备案号:备案中。