[Vue]之Jwt的入门和Jwt工具类的使用及Jwt集成spa项目

一,jwt入门

1.1 是什么?

         JWT,全称为 JSON Web Token,是一种用于在网络应用之间传递信息的标准方法。它是基于 JSON 格式定义的一种简洁且自包含的方式,可以安全地在用户和服务之间传输声明信息

1.2 为什么要使用

①简洁性JWT 的格式简洁且体积小,可以方便地在网络请求的头部、参数或者正文中传输

②自包含性:JWT 内部包含了所有的认证信息,因此服务端不需要针对每个请求都去查询数据库或者进行其他的操作来验证请求的合法性

③跨平台支持:由于 JWT 使用的是标准的 JSON 格式,因此在不同平台的应用中都可以方便地使用

JWT的精髓在于:“去中心化”,数据是保存在客户端的

1.3 工作原理

用户通过用户名和密码等方式进行登录认证

服务端验证用户提供的凭据信息,如果验证通过,则在服务端生成一个 JWT

服务端将生成的 JWT 返回给客户端

客户端在每次发送请求时,都需要在请求头部或者其他地方添加生成的 JWT

服务端接收到请求后,验证 JWT 的合法性,如果验证通过,则处理请求;否则,返回未授权的错误信息

1.4 核心组成(三部分)

  • 头部(Header):包含了 JWT 的类型(“typ”)和使用的签名算法(“alg”)

  • 载荷(Payload):是 JWT 实际存放信息的地方,包含了一些声明(claims),例如用户的身份信息、权限等

  • 签名(Signature):由头部和载荷进行签名生成,用于验证 JWT 的合法性

二,jwt的工具类

2.1 JwtUtils:

package com.zking.ssm.jwt;import java.util.Date;
import java.util.Map;
import java.util.UUID;import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;import org.apache.commons.codec.binary.Base64;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;/*** JWT验证过滤器:配置顺序 CorsFilte->JwtUtilsr-->StrutsPrepareAndExecuteFilter**/
public class JwtUtils {/*** JWT_WEB_TTL:WEBAPP应用中token的有效时间,默认30分钟*/public static final long JWT_WEB_TTL = 30 * 60 * 1000;/*** 将jwt令牌保存到header中的key*/public static final String JWT_HEADER_KEY = "jwt";// 指定签名的时候使用的签名算法,也就是header那部分,jwt已经将这部分内容封装好了。private static final SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS256;private static final String JWT_SECRET = "f356cdce935c42328ad2001d7e9552a3";// JWT密匙private static final SecretKey JWT_KEY;// 使用JWT密匙生成的加密keystatic {byte[] encodedKey = Base64.decodeBase64(JWT_SECRET);JWT_KEY = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");}private JwtUtils() {}/*** 解密jwt,获得所有声明(包括标准和私有声明)* * @param jwt* @return* @throws Exception*/public static Claims parseJwt(String jwt) {Claims claims = Jwts.parser().setSigningKey(JWT_KEY).parseClaimsJws(jwt).getBody();return claims;}/*** 创建JWT令牌,签发时间为当前时间* * @param claims*            创建payload的私有声明(根据特定的业务需要添加,如果要拿这个做验证,一般是需要和jwt的接收方提前沟通好验证方式的)* @param ttlMillis*            JWT的有效时间(单位毫秒),当前时间+有效时间=过期时间* @return jwt令牌*/public static String createJwt(Map<String, Object> claims, long ttlMillis) {// 生成JWT的时间,即签发时间 2021-10-30 10:02:00 -> 30 10:32:00long nowMillis = System.currentTimeMillis();//链式语法:// 下面就是在为payload添加各种标准声明和私有声明了// 这里其实就是new一个JwtBuilder,设置jwt的bodyJwtBuilder builder = Jwts.builder()// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的.setClaims(claims)// 设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。// 可以在未登陆前作为身份标识使用.setId(UUID.randomUUID().toString().replace("-", ""))// iss(Issuser)签发者,写死.setIssuer("zking")// iat: jwt的签发时间.setIssuedAt(new Date(nowMillis))// 代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串,可放数据{"uid":"zs"}。此处没放// .setSubject("{}")// 设置签名使用的签名算法和签名使用的秘钥.signWith(SIGNATURE_ALGORITHM, JWT_KEY)// 设置JWT的过期时间.setExpiration(new Date(nowMillis + ttlMillis));return builder.compact();}/*** 复制jwt,并重新设置签发时间(为当前时间)和失效时间* * @param jwt*            被复制的jwt令牌* @param ttlMillis*            jwt的有效时间(单位毫秒),当前时间+有效时间=过期时间* @return*/public static String copyJwt(String jwt, Long ttlMillis) {//解密JWT,获取所有的声明(私有和标准)//oldClaims claims = parseJwt(jwt);// 生成JWT的时间,即签发时间long nowMillis = System.currentTimeMillis();// 下面就是在为payload添加各种标准声明和私有声明了// 这里其实就是new一个JwtBuilder,设置jwt的bodyJwtBuilder builder = Jwts.builder()// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的.setClaims(claims)// 设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。// 可以在未登陆前作为身份标识使用//.setId(UUID.randomUUID().toString().replace("-", ""))// iss(Issuser)签发者,写死// .setIssuer("zking")// iat: jwt的签发时间.setIssuedAt(new Date(nowMillis))// 代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串,可放数据{"uid":"zs"}。此处没放// .setSubject("{}")// 设置签名使用的签名算法和签名使用的秘钥.signWith(SIGNATURE_ALGORITHM, JWT_KEY)// 设置JWT的过期时间.setExpiration(new Date(nowMillis + ttlMillis));return builder.compact();}
}

该工具类提供了以下几个方法:

        parseJwt(String jwt):解密JWT,获得所有声明。

        参数:jwt - 要解密的JWT令牌。
        返回值:包含所有声明的Claims对象。
 createJwt(Map<String, Object> claims, long ttlMillis):创建JWT令牌,签发时间为当前时间。

        参数:claims - 创建payload的私有声明。 ttlMillis - JWT的有效时间(单位毫秒)。
        返回值:生成的JWT令牌。
 copyJwt(String jwt, Long ttlMillis):复制JWT,并重新设置签发时间和失效时间。

        参数:jwt - 被复制的JWT令牌。 ttlMillis - JWT的有效时间(单位毫秒)。
        返回值:生成的新的JWT令牌

2.1 生成JWT

package com.zking.ssm.service.impl;import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;import com.zking.ssm.jwt.JwtUtils;
import io.jsonwebtoken.Claims;
import org.junit.*;public class JwtDemo {private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");@Testpublic void test1() {// 生成JWT//JWT Token=Header.Payload.Signature//头部.载荷.签名//Payload=标准声明+私有声明+公有声明//定义私有声明Map<String, Object> claims = new HashMap<String, Object>();claims.put("username", "zss");claims.put("age", 18);//TTL:Time To LiveString jwt = JwtUtils.createJwt(claims, JwtUtils.JWT_WEB_TTL);System.out.println(jwt);//获取Payload(包含标准和私有声明)Claims parseJwt = JwtUtils.parseJwt(jwt);for (Map.Entry<String, Object> entry : parseJwt.entrySet()) {System.out.println(entry.getKey() + "=" + entry.getValue());}Date d1 = parseJwt.getIssuedAt();Date d2 = parseJwt.getExpiration();System.out.println("令牌签发时间:" + sdf.format(d1));System.out.println("令牌过期时间:" + sdf.format(d2));}@Testpublic void test2() {// 解析oldJwt//io.jsonwebtoken.ExpiredJwtException:JWT过期异常//io.jsonwebtoken.SignatureException:签名异常//String oldJwt="eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1OTA3MTg2NzcsImlhdCI6MTU5MDcxNjg3NywiYWdlIjoxOCwianRpIjoiNDFmZjFiZGFkYzkxNDA3OGE4ZGUyNGRkZDEwYjU4N2IiLCJ1c2VybmFtZSI6InpzcyJ9.DdPvioX6kuhV6lEfD9QAN2eQSk_mO3dYkmDmTQsqa78";//eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MzU1NjE3MjcsImlhdCI6MTYzNTU1OTkyNywiYWdlIjoxOCwianRpIjoiN2RlYmIzM2JiZTg3NDBmODgzNDI5Njk0ZWE4NzcyMTgiLCJ1c2VybmFtZSI6InpzcyJ9.dUR-9JUlyRdoYx-506SxXQ3gbHFCv0g5Zm8ZGzK1fzwString newJwt="eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ6a2luZyIsImV4cCI6MTY2MjM0Njg3MSwiaWF0IjoxNjYyMzQ1MDcxLCJhZ2UiOjE4LCJqdGkiOiI4YjllNzc3YzFlMDM0MjViYThmMDVjNTFlMTU3NDQ1MiIsInVzZXJuYW1lIjoienNzIn0.UWpJxPxwJ09PKxE2SY5ME41W1Kv3jP5bZGKK-oNUDuM";String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MzU1NjE3MjcsImlhdCI6MTYzNTU1OTkyNywiYWdlIjoxOCwianRpIjoiN2RlYmIzM2JiZTg3NDBmODgzNDI5Njk0ZWE4NzcyMTgiLCJ1c2VybmFtZSI6InpzcyJ9.dUR-9JUlyRdoYx-506SxXQ3gbHFCv0g5Zm8ZGzK1fzw";Claims parseJwt = JwtUtils.parseJwt(newJwt);for (Map.Entry<String, Object> entry : parseJwt.entrySet()) {System.out.println(entry.getKey() + "=" + entry.getValue());}Date d1 = parseJwt.getIssuedAt();Date d2 = parseJwt.getExpiration();System.out.println("令牌签发时间:" + sdf.format(d1));System.out.println("令牌过期时间:" + sdf.format(d2));}@Testpublic void test3() {// 复制jwt,并延时30分钟String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ6a2luZyIsImV4cCI6MTY2MjM0Njg3MSwiaWF0IjoxNjYyMzQ1MDcxLCJhZ2UiOjE4LCJqdGkiOiI4YjllNzc3YzFlMDM0MjViYThmMDVjNTFlMTU3NDQ1MiIsInVzZXJuYW1lIjoienNzIn0.UWpJxPxwJ09PKxE2SY5ME41W1Kv3jP5bZGKK-oNUDuM";//String newJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MDU3NTM2NTUsImlhdCI6MTYwNTc1MTg1NSwiYWdlIjoxOCwianRpIjoiYmNmN2Q1MzQ2YjE3NGU2MDk1MmIxYzQ3ZTlmMzQyZjgiLCJ1c2VybmFtZSI6InpzcyJ9.m1Qn84RxgbKCnsvrdbbAnj8l_5Jwovry8En0j4kCxhc";//String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjI5MDMzNjAsImlhdCI6MTU2MjkwMTU2MCwiYWdlIjoxOCwianRpIjoiZDVjMzE4Njg0MDcyNDgyZDg1MDE5ODVmMDY3OGQ4NjkiLCJ1c2VybmFtZSI6InpzcyJ9.XDDDRRq5jYq5EdEBHtPm7GcuBz4S0VhDTS1amRCdf48";String newJwt = JwtUtils.copyJwt(oldJwt, JwtUtils.JWT_WEB_TTL);System.out.println(newJwt);Claims parseJwt = JwtUtils.parseJwt(newJwt);for (Map.Entry<String, Object> entry : parseJwt.entrySet()) {System.out.println(entry.getKey() + "=" + entry.getValue());}Date d1 = parseJwt.getIssuedAt();Date d2 = parseJwt.getExpiration();System.out.println("令牌签发时间:" + sdf.format(d1));System.out.println("令牌过期时间:" + sdf.format(d2));}@Testpublic void test4() {// 测试JWT的有效时间Map<String, Object> claims = new HashMap<String, Object>();claims.put("username", "zss");String jwt = JwtUtils.createJwt(claims, 3 * 1000L);System.out.println(jwt);Claims parseJwt = JwtUtils.parseJwt(jwt);Date d1 = parseJwt.getIssuedAt();Date d2 = parseJwt.getExpiration();System.out.println("令牌签发时间:" + sdf.format(d1));System.out.println("令牌过期时间:" + sdf.format(d2));}@Testpublic void test5() {// 三秒后再解析上面过期时间只有三秒的令牌,因为过期则会报错io.jsonwebtoken.ExpiredJwtException//String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MzU1NjMzODIsImlhdCI6MTYzNTU2MTU4MiwiYWdlIjoxOCwianRpIjoiN2RlYmIzM2JiZTg3NDBmODgzNDI5Njk0ZWE4NzcyMTgiLCJ1c2VybmFtZSI6InpzcyJ1.F4pZFCjWP6wlq8v_udfhOkNCpErF5QlL7DXJdzXTHqE";String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ6a2luZyIsImV4cCI6MTY2MjM0Njg3MSwiaWF0IjoxNjYyMzQ1MDcxLCJhZ2UiOjE4LCJqdGkiOiI4YjllNzc3YzFlMDM0MjViYThmMDVjNTFlMTU3NDQ1MiIsInVzZXJuYW1lIjoienNzIn9.UWpJxPxwJ09PKxE2SY5ME41W1Kv3jP5bZGKK-oNUDuM";Claims parseJwt = JwtUtils.parseJwt(oldJwt);// 过期后解析就报错了,下面代码根本不会执行Date d1 = parseJwt.getIssuedAt();Date d2 = parseJwt.getExpiration();System.out.println("令牌签发时间:" + sdf.format(d1));System.out.println("令牌过期时间:" + sdf.format(d2));}
}

     用于生成JWT。在该方法中,定义了私有声明(claims),并设置了一些键值对,例如用户名和年龄。然后调用了JwtUtils.createJwt()方法生成JWT,并打印输出。

2.2 解析JWT

用test2()进行解析  

用以上生成的JWT字符串进行解析

	@Testpublic void test2() {// 解析oldJwt//io.jsonwebtoken.ExpiredJwtException:JWT过期异常//io.jsonwebtoken.SignatureException:签名异常//String oldJwt="eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1OTA3MTg2NzcsImlhdCI6MTU5MDcxNjg3NywiYWdlIjoxOCwianRpIjoiNDFmZjFiZGFkYzkxNDA3OGE4ZGUyNGRkZDEwYjU4N2IiLCJ1c2VybmFtZSI6InpzcyJ9.DdPvioX6kuhV6lEfD9QAN2eQSk_mO3dYkmDmTQsqa78";//eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MzU1NjE3MjcsImlhdCI6MTYzNTU1OTkyNywiYWdlIjoxOCwianRpIjoiN2RlYmIzM2JiZTg3NDBmODgzNDI5Njk0ZWE4NzcyMTgiLCJ1c2VybmFtZSI6InpzcyJ9.dUR-9JUlyRdoYx-506SxXQ3gbHFCv0g5Zm8ZGzK1fzwString newJwt="eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ6a2luZyIsImV4cCI6MTY2MjM0Njg3MSwiaWF0IjoxNjYyMzQ1MDcxLCJhZ2UiOjE4LCJqdGkiOiI4YjllNzc3YzFlMDM0MjViYThmMDVjNTFlMTU3NDQ1MiIsInVzZXJuYW1lIjoienNzIn0.UWpJxPxwJ09PKxE2SY5ME41W1Kv3jP5bZGKK-oNUDuM";String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MzU1NjE3MjcsImlhdCI6MTYzNTU1OTkyNywiYWdlIjoxOCwianRpIjoiN2RlYmIzM2JiZTg3NDBmODgzNDI5Njk0ZWE4NzcyMTgiLCJ1c2VybmFtZSI6InpzcyJ9.dUR-9JUlyRdoYx-506SxXQ3gbHFCv0g5Zm8ZGzK1fzw";Claims parseJwt = JwtUtils.parseJwt(newJwt);for (Map.Entry<String, Object> entry : parseJwt.entrySet()) {System.out.println(entry.getKey() + "=" + entry.getValue());}Date d1 = parseJwt.getIssuedAt();Date d2 = parseJwt.getExpiration();System.out.println("令牌签发时间:" + sdf.format(d1));System.out.println("令牌过期时间:" + sdf.format(d2));}

用于解析JWT。在该方法中,使用JwtUtils.parseJwt()方法解析了一个旧的JWT,并将解析结果打印输出。

2.3 复制JWT并延时30分钟

@Testpublic void test3() {// 复制jwt,并延时30分钟String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ6a2luZyIsImV4cCI6MTY5NzIwMzU4OCwiaWF0IjoxNjk3MjAxNzg4LCJhZ2UiOjE4LCJqdGkiOiI3YzU4YzNkMDk4OTA0YmE5OTMxMGJhZTRmYWFiMjU0NyIsInVzZXJuYW1lIjoienNzIn0.y7RS88Ionnt12k6WNbLm-6-qw61RtpYrYnUUMAyAWZg";//String newJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MDU3NTM2NTUsImlhdCI6MTYwNTc1MTg1NSwiYWdlIjoxOCwianRpIjoiYmNmN2Q1MzQ2YjE3NGU2MDk1MmIxYzQ3ZTlmMzQyZjgiLCJ1c2VybmFtZSI6InpzcyJ9.m1Qn84RxgbKCnsvrdbbAnj8l_5Jwovry8En0j4kCxhc";//String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjI5MDMzNjAsImlhdCI6MTU2MjkwMTU2MCwiYWdlIjoxOCwianRpIjoiZDVjMzE4Njg0MDcyNDgyZDg1MDE5ODVmMDY3OGQ4NjkiLCJ1c2VybmFtZSI6InpzcyJ9.XDDDRRq5jYq5EdEBHtPm7GcuBz4S0VhDTS1amRCdf48";String newJwt = JwtUtils.copyJwt(oldJwt, JwtUtils.JWT_WEB_TTL);System.out.println(newJwt);Claims parseJwt = JwtUtils.parseJwt(newJwt);for (Map.Entry<String, Object> entry : parseJwt.entrySet()) {System.out.println(entry.getKey() + "=" + entry.getValue());}Date d1 = parseJwt.getIssuedAt();Date d2 = parseJwt.getExpiration();System.out.println("令牌签发时间:" + sdf.format(d1));System.out.println("令牌过期时间:" + sdf.format(d2));}

用于复制JWT并延时30分钟。在该方法中,使用JwtUtils.copyJwt()方法复制了一个旧的JWT,并设置了新的过期时间,并将复制后的JWT打印输出

2.4 测试JWT的有效时间

@Testpublic void test4() {// 测试JWT的有效时间Map<String, Object> claims = new HashMap<String, Object>();claims.put("username", "zss");String jwt = JwtUtils.createJwt(claims, 3 * 1000L);System.out.println(jwt);Claims parseJwt = JwtUtils.parseJwt(jwt);Date d1 = parseJwt.getIssuedAt();Date d2 = parseJwt.getExpiration();System.out.println("令牌签发时间:" + sdf.format(d1));System.out.println("令牌过期时间:" + sdf.format(d2));}

用于测试JWT的有效时间。在该方法中,创建了一个带有有效时间为3秒的JWT,并将其打印输出

2.5 模拟过期JWT的解析

@Testpublic void test5() {// 三秒后再解析上面过期时间只有三秒的令牌,因为过期则会报错io.jsonwebtoken.ExpiredJwtException//String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MzU1NjMzODIsImlhdCI6MTYzNTU2MTU4MiwiYWdlIjoxOCwianRpIjoiN2RlYmIzM2JiZTg3NDBmODgzNDI5Njk0ZWE4NzcyMTgiLCJ1c2VybmFtZSI6InpzcyJ1.F4pZFCjWP6wlq8v_udfhOkNCpErF5QlL7DXJdzXTHqE";String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ6a2luZyIsImV4cCI6MTY5NzIwMzU4OCwiaWF0IjoxNjk3MjAxNzg4LCJhZ2UiOjE4LCJqdGkiOiI3YzU4YzNkMDk4OTA0YmE5OTMxMGJhZTRmYWFiMjU0NyIsInVzZXJuYW1lIjoienNzIn0.y7RS88Ionnt12k6WNbLm-6-qw61RtpYrYnUUMAyAWZg";Claims parseJwt = JwtUtils.parseJwt(oldJwt);// 过期后解析就报错了,下面代码根本不会执行Date d1 = parseJwt.getIssuedAt();Date d2 = parseJwt.getExpiration();System.out.println("令牌签发时间:" + sdf.format(d1));System.out.println("令牌过期时间:" + sdf.format(d2));}
}

用于模拟过期JWT的解析。在该方法中,尝试解析一个过期的JWT,并会抛出io.jsonwebtoken.ExpiredJwtException异常。

三,jwt前后端分离

1.user登录方法,要放开用户信息生成jwt串保存到响应头中的代码

2.关闭jwtfilter中的off开关,代表开启jwt验证

3.crosfilter中要允许jwt使用请求头及响应头,换句话说web.xml要更换配置

后端user

JwtFilter 

package com.zking.ssm.jwt;import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import io.jsonwebtoken.Claims;/*** * JWT验证过滤器,配置顺序 :CorsFilter-->JwtFilter-->struts2中央控制器* * @author Administrator**/public class JwtFilter implements Filter {// 排除的URL,一般为登陆的URL(请改成自己登陆的URL)private static String EXCLUDE = "^/user/userLogin?.*$";private static Pattern PATTERN = Pattern.compile(EXCLUDE);private boolean OFF = false;// true关闭jwt令牌验证功能@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void destroy() {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) request;HttpServletResponse resp = (HttpServletResponse) response;//获取当前请求路径。只有登录的请求路径不进行校验之外,其他的URL请求路径必须进行JWT令牌校验//http://localhost:8080/ssh2/bookAction_queryBookPager.action//req.getServletPath()==/bookAction_queryBookPager.actionString path = req.getServletPath();if (OFF || isExcludeUrl(path)) {// 登陆直接放行chain.doFilter(request, response);return;}// 从客户端请求头中获得令牌并验证//token=头.载荷.签名String jwt = req.getHeader(JwtUtils.JWT_HEADER_KEY);Claims claims = this.validateJwtToken(jwt);//在这里请各位大哥大姐从JWT令牌中提取payload中的声明部分//从声明部分中获取私有声明//获取私有声明中的User对象 -> ModulesBoolean flag=false;if (null == claims) {// resp.setCharacterEncoding("UTF-8");resp.sendError(403, "JWT令牌已过期或已失效");return;} else {//1.获取已经解析后的payload(私有声明)//2.从私有声明中当前用户所对应的权限集合List<String>或者List<Module>//3.循环权限(Module[id,url])// OK,放行请求 chain.doFilter(request, response);// NO,发送错误信息的JSON// ObjectMapper mapper=new ObjectMapper()// mapper.writeValue(response.getOutputStream(),json)String newJwt = JwtUtils.copyJwt(jwt, JwtUtils.JWT_WEB_TTL);resp.setHeader(JwtUtils.JWT_HEADER_KEY, newJwt);chain.doFilter(request, response);}}/*** 验证jwt令牌,验证通过返回声明(包括公有和私有),返回null则表示验证失败*/private Claims validateJwtToken(String jwt) {Claims claims = null;try {if (null != jwt) {//该解析方法会验证:1)是否过期 2)签名是否成功claims = JwtUtils.parseJwt(jwt);}} catch (Exception e) {e.printStackTrace();}return claims;}/*** 是否为排除的URL* * @param path* @return*/private boolean isExcludeUrl(String path) {Matcher matcher = PATTERN.matcher(path);return matcher.matches();}// public static void main(String[] args) {// String path = "/sys/userAction_doLogin.action?username=zs&password=123";// Matcher matcher = PATTERN.matcher(path);// boolean b = matcher.matches();// System.out.println(b);// }}

运用之前我们就要问到我们的跨域问题了,我们要运用这个跨域问题

CorsFilter 

package com.zking.ssm.util;import java.io.IOException;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** 配置tomcat允许跨域访问* * @author Administrator**/
public class CorsFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)throws IOException, ServletException {HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;HttpServletRequest req = (HttpServletRequest) servletRequest;// Access-Control-Allow-Origin就是我们需要设置的域名// Access-Control-Allow-Headers跨域允许包含的头。// Access-Control-Allow-Methods是允许的请求方式httpResponse.setHeader("Access-Control-Allow-Origin", "*");// *,任何域名httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE");//允许客户端发一个新的请求头jwthttpResponse.setHeader("Access-Control-Allow-Headers","responseType,Origin,X-Requested-With, Content-Type, Accept, jwt");//允许客户端处理一个新的响应头jwthttpResponse.setHeader("Access-Control-Expose-Headers", "jwt,Content-Disposition");//httpResponse.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");//httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE");// axios的ajax会发两次请求,第一次提交方式为:option,直接返回即可if ("OPTIONS".equals(req.getMethod())) {return;}filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {}
}

web.xml:

  <!--CrosFilter跨域过滤器--><filter><filter-name>corsFilter</filter-name><filter-class>com.zking.ssm.util.CorsFilter</filter-class></filter><filter-mapping><filter-name>corsFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>

state.js:

export default{eduName:'我不是打工人',jwt: ''
}

mutations.js:

export default{setEduName:(state,payload)=>{state.eduName=payload.eduName},setJwt: (state, payload) => {state.jwt = payload.jwt;}}

gettter.js:

export default{getEduName:(state)=>{return state.eduName;},getJwt: (state) => {return state.jwt;}}

http.js:

// 请求拦截器
axios.interceptors.request.use(function (config) {var jwt = window.ss.$store.getters.getJwtif (jwt) {config.headers['jwt']=jwt}return config;
}, function (error) {return Promise.reject(error);
});// 响应拦截器
axios.interceptors.response.use(function (response) {let jwt = response.headers['jwt'];if (jwt) {//将响应头中的jwt串放入state.js中window.ss.$store.commit('setJwt', {jwt: jwt})}return response;
}, function (error) {return Promise.reject(error);
});

mian.js

/* eslint-disable no-new */
window.ss=new Vue({el: '#app',router,store, //在main.js中导入store实例data(){return{Bus:new Vue()}},components: { App },template: '<App/>'
})

效果图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/157789.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue面试题-应用层

MVC与MVVM MVCMVVM 双向数据绑定 vue2 双向绑定原理 v-model原理 vue3 双向绑定原理 示例 对比 vue2响应式原理和Vue3响应式原理 data为什么是函数?v-if 与 v-show MVC与MVVM MVC和MVVM是两种流行的设计模式&#xff0c;它们都是用于构建动态应用程序的框架。 MVC MVC&#…

Jetson Orin NX 开发指南(7): EGO-Swarm 的编译与运行

一、前言 EGO-Planner 浙江大学 FAST-LAB 实验室的开源轨迹规划算法是&#xff0c;受到 IEEE Spectrum 等知名科技媒体的报道&#xff0c;其理论技术较为前沿&#xff0c;是一种不依赖于ESDF&#xff0c;基于B样条的规划算法&#xff0c;并且规划成功率、算法消耗时间、代价数…

openGauss学习笔记-98 openGauss 数据库管理-管理数据库安全-客户端接入认证之配置客户端接入认证

文章目录 openGauss学习笔记-98 openGauss 数据库管理-管理数据库安全-客户端接入认证之配置客户端接入认证98.1 背景信息98.2 操作步骤98.3 异常处理98.4 示例 openGauss学习笔记-98 openGauss 数据库管理-管理数据库安全-客户端接入认证之配置客户端接入认证 98.1 背景信息 …

Gpt-4多模态功能强势上线,景联文科技多模态数据采集标注服务等您来体验!

就在上个月&#xff0c;OpenAI 宣布对ChatGPT 进行重大更新&#xff0c;该模型不仅能够通过文字输入进行识别和分析&#xff0c;还能够通过语音、图像甚至视频等多种模态的输入来获取、识别、分析和输出信息。这一重要技术突破&#xff0c;将促进多模态自然语言处理的发展&…

Jmeter脚本参数化和正则匹配

我们在做接口测试过程中&#xff0c;往往会遇到以下几种情况 每次发送请求&#xff0c;都需要更改参数值为未使用的参数值&#xff0c;比如手机号注册、动态时间等 上一个接口的请求体参数用于下一个接口的请求体参数 上一个接口的响应体参数用于下一个接口的请求体参数&#…

private key ssh连接服务器

这里用到的软件是PuTTY。 https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html 保存本地rsa文件后&#xff0c;打开软件PuTTYgen&#xff0c;点击Load导入文件&#xff0c;输入Key passphrase即密码&#xff0c;保存至本地。 随后在PuTTY配置ssh的用户名 来Cred…

基于Linux安装Hive

Hive安装包下载地址 Index of /dist/hive 上传解压 [rootmaster opt]# cd /usr/local/ [rootmaster local]# tar -zxvf /opt/apache-hive-3.1.2-bin.tar.gz重命名及更改权限 mv apache-hive-3.1.2-bin hivechown -R hadoop:hadoop hive配置环境变量 #编辑配置 vi /etc/pro…

MySQL——源码安装教程

MySQL 一、MySQL的安装1、RPM2、二进制3、源码 二、源码安装方式三、安装过程1、上传源码包2、解压当前文件并安装更新依赖3、对MySQL进行编译安装 四、其他步骤 一、MySQL的安装 首先这里我来介绍下MySQL的几种安装方式&#xff1a; 一共三种&#xff0c;RPM安装包、二进制包…

数据库第三次作业

1、使用源码安装MySQL8.0.x。 进入MySQL官方网站中下载适合你操作系统的源代码包MySQLhttps://www.mysql.com/复制下载链接&#xff0c;用wget命令安装。 [rootlocalhost ~]# wget https://repo.mysql.com//mysql80-community-release-el9-4.noarch.rpm [rootlocalhost ~]# r…

详解cv2.addWeighted函数【使用 OpenCV 添加(混合)两个图像-Python版本】

文章目录 简介函数原型代码示例参考资料 简介 有的时候我们需要将两张图片在alpha通道进行混合&#xff0c;比如深度学习数据集增强方式MixUp。OpenCV的addWeighted提供了相关操作&#xff0c;瓷片博客将详细介绍这个函数&#xff0c;并给出代码示例。&#x1f680;&#x1f6…

MTK6877/MT6877天玑900安卓5G核心板_安卓开发板主板定制开发

2021年5月13日&#xff0c;MediaTek 宣布发布旗下的天玑900系列芯片&#xff0c;又名MT6877。天玑900基于6nm先进工艺制造&#xff0c;搭载硬件级4K HDR视频录制引擎&#xff0c;支持1.08亿像素摄像头、5G双全网通和Wi-Fi 6连接、旗舰级存储规格和120Hz的FHD超高清分辨率显示&a…

华为汪涛:5.5G时代UBB目标网,跃升数字生产力

[阿联酋&#xff0c;迪拜&#xff0c;2023年10月12日] 在2023全球超宽带高峰论坛上&#xff0c;华为常务董事、ICT基础设施业务管理委员会主任汪涛发表了“5.5G时代UBB目标网&#xff0c;跃升数字生产力”的主题发言&#xff0c;分享了超宽带产业的最新思考与实践&#xff0c;探…

Spring实战 | Spring AOP核心功能分析之葵花宝典

国庆中秋特辑系列文章&#xff1a; 国庆中秋特辑&#xff08;八&#xff09;Spring Boot项目如何使用JPA 国庆中秋特辑&#xff08;七&#xff09;Java软件工程师常见20道编程面试题 国庆中秋特辑&#xff08;六&#xff09;大学生常见30道宝藏编程面试题 国庆中秋特辑&…

uniapp 一次性上传多条视频 u-upload accept=“video“ uni.chooseMedia uni.uploadFile

方式 一 部分安卓机 只能一条一条传视频 文档地址 uview 2.0 Upload 上传组件 html <view class"formupload"><u-upload accept"video":fileList"fileList3" afterRead"afterRead" delete"deletePic" name"…

[Swift]同一个工程管理多个Target

1.准备 先创建一个测试工程“ADemo”&#xff0c;右键其Target选择Duplicate&#xff0c;再复制一个Target为“ADemo2”。 再选择TARGETS下方的“”&#xff0c;添加一个APP到项目中&#xff0c;这个命名为“BDemo”。 2、管理多个Target 可以对三个target分别导入不同的框…

学信息系统项目管理师第4版系列26_项目绩效域(下)

1. 项目工作绩效域 1.1. 涉及项目工作相关的活动和职能 1.2. 预期目标 1.2.1. 高效且有效的项目绩效 1.2.2. 适合项目和环境的项目过程 1.2.3. 干系人适当的沟通和参与 1.2.4. 对实物资源进行了有效管理 1.2.5. 对采购进行了有效管理 1.2.6. 有效处理了变更 1.2.7. 通…

软件测试学习(四)自动测试和测试工具、缺陷轰炸、外包测试、计划测试工作、编写和跟踪测试用例

目录 自动测试和测试工具 工具和自动化的好处 测试工具 查看器和监视器 驱动程序 桩 压力和负载工具 干扰注入器和噪声发生器 分析工具 软件测试自动化 宏录制和回放 可编程的宏 完全可编程的自动测试工具 随机测试&#xff1a;猴子和大猩猩 使用测试工具和自动…

权限管理与jwt鉴权

权限管理与jwt鉴权 学习目标&#xff1a; 理解权限管理的需求以及设计思路实现角色分配和权限分配 理解常见的认证机制 能够使用JWT完成微服务Token签发与验证 权限管理 需求分析 完成权限&#xff08;菜单&#xff0c;按钮&#xff08;权限点&#xff09;&#xff0c;A…

TiDB 7.4 发版:正式兼容 MySQL 8.0

MySQL 是全球最受欢迎的开源数据库&#xff0c;长期位于 DB-Engines Ranking 排行榜第二名&#xff0c;在世界范围内拥有数量庞大的企业用户和开发者。然而&#xff0c;随着时间的推移&#xff0c;MySQL 用户正面临新挑战。Oracle 官宣将在 2023 年 10 月终止 MySQL 5.7 版本的…

LeetCode【739】每日温度

题目&#xff1a; 思路&#xff1a; https://www.bilibili.com/video/BV1PJ411H7P7/?spm_id_from333.337.search-card.all.click&vd_source2f682a60feabf0f730ad09e0f980ce83 单调栈 思考&#xff1a; 解决栈类问题&#xff0c;思考入栈&#xff0c;出栈条件&#xff1b;…