JSON Web Token(JWT)是目前都在用的前后分离跨域验证规则。
JWT由3部分组成
1、引入依赖pom.xml
com.auth0 java-jwt 3.8.2
2、编写jwt工具类JwtUtil.java
package com.muchuantong.util;import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;/*** @Author: Zou Tiancong* @Date: 2021/12/1 0001 10:37* @Annotation:jwtToken*/
public class JwtUtil {// 设置过期时间private static final long EXPIRE_DATE = 60*1000;// token秘钥private static final String TOKEN_SECRET = "TEST-AUTH-TOKEN";// 实现签名方法public static String token(String id, String openId, String nickName) {String token = "";try {// 这里将用户存入了Token,在下面的解析中,也会有解析的方法可以获取到Token里面的数据// Token过期的时间Date expireDate = new Date(System.currentTimeMillis() + EXPIRE_DATE);// 秘钥及加密算法Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);// 设置头部信息,类型以及签名所用的算法Map header = new HashMap<>();header.put("typ", "JWT");header.put("alg", "HS256");// 携带用户信息,存入token,生成签名token = JWT.create().withHeader(header) //设置头部信息Header.withIssuer("TEST") //设置签名是由谁生成.withSubject("AUTH-TOKEN") //设置签名的主题.withAudience(nickName) //设置签名的观众.withIssuedAt(new Date()) //设置生成签名的时间.withExpiresAt(expireDate) //设置签名过期的时间.withClaim("id", id) //自定义信息.withClaim("openId", openId)//自定义信息.withClaim("nickName", nickName)//自定义信息.withJWTId(id) //jwt的id,主要用来作为一次性token,从而回避重放攻击.sign(algorithm);} catch (Exception e) {e.printStackTrace();return null;}return token;}// 验证tokenpublic static boolean verify(String token) {/*** @desc 验证token,通过返回true* @params [token]需要校验的串**/try {Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);JWTVerifier verifier = JWT.require(algorithm).build();DecodedJWT jwt = verifier.verify(token);String subject = jwt.getSubject();List audience = jwt.getAudience();Map claims = jwt.getClaims();System.out.println(subject+"*******"+audience);for (Map.Entry entry : claims.entrySet()){String key = entry.getKey();Claim claim = entry.getValue();String value = claim.asString();System.out.println("key:"+key+" value:"+value);}return true;} catch (Exception e) {e.printStackTrace();System.out.println("Token已过期,需要重新登录");}return false;}// 生成tokenpublic static String setToken(String id, String openId, String nickName) {String token = token(id, openId, nickName);return token;}}
2、自定义注解接口Auth.java
package com.muchuantong.util;import java.lang.annotation.*;/*** Created with IntelliJ IDEA.** @Auther: ZouTiancong* @Date: 2022/05/23/22:37* @Description:*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Auth {boolean token() default true;
}
3、自定义注解APO实现类AuthAspect.java
package com.muchuantong.util;import javax.servlet.http.HttpServletRequest;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** Created with IntelliJ IDEA.** @Auther: ZouTiancong* @Date: 2022/05/23/22:39* @Description:*/
@Component
@Aspect
public class AuthAspect {@Autowiredprivate HttpServletRequest request;@Pointcut("@annotation(com.muchuantong.util.Auth)")private void authPointcut() {}@Around("authPointcut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {// 获取方法签名信息从而获取方法名和参数类型MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();// 获取目标方法对象上注解中的属性值Auth auth = methodSignature.getMethod().getAnnotation(Auth.class);// 校验签名if (auth.token()) {boolean token = JwtUtil.verify(request.getHeader("token"));// 如果token校验失败返回if (!token) {return new Result<>("401", "token已过期,请重新登录!");}}return joinPoint.proceed();}
}
4、在需要token验证的地方加入注解@Auth
5、前端调用查看效果,token生成返回成功,后端也能成功读取数据