SpringBoot Aop 简单实现Token登录校验

一、前言:

Java开发中有很多登录Token解决方案 下面我给大家总结如何使用SpringAop实现简单Token拦截

二、相关依赖Maven:

		 <!--鉴权-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.0</version>
        </dependency>
        <!-- aop 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
            <version>2.4.1</version>
        </dependency>

三、实际代码:

JWT工具类:

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.Objects;

/**
 * @author zhu
 * @date 2021/6/1 14:49
 * JWT工具类
 */
public class JwtUtil {
    
    

    /**
     * 有效期为60 * 60 *1000  一个小时
     */
    public static final Long JWT_TTL = 3600000L;
    /**
     * 设置秘钥明文
     */
    public static final String JWT_KEY = "njcool";

    /**
     * 创建token
     *
     * @param id        唯一标识
     * @param subject   主题
     * @param ttlMillis 时间
     * @return token
     */
    public static String createJWT(String id, String subject, Long ttlMillis) {
    
    
        //获取当前系统时间
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        if (Objects.isNull(ttlMillis)) {
    
    
            ttlMillis = JwtUtil.JWT_TTL;
        }
        //设置过期时间
        long expMillis = nowMillis + ttlMillis;
        Date expDate = new Date(expMillis);
        SecretKey secretKey = generalKey();
        //创建Token
        JwtBuilder builder = Jwts.builder()
                //唯一的ID
                .setId(id)
                // 主题  可以是JSON数据
                .setSubject(subject)
                // 签发者
                .setIssuer("admin")
                // 签发时间
                .setIssuedAt(now)
                //使用HS256对称加密算法签名, 第二个参数为秘钥
                .signWith(SignatureAlgorithm.HS256, secretKey)
                // 设置过期时间
                .setExpiration(expDate);
        return builder.compact();
    }

    /**
     * 生成加密后的秘钥 secretKey
     *
     * @return 针对秘钥进行二次加密
     */
    public static SecretKey generalKey() {
    
    
        byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
        return new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
    }

    /**
     * 解析
     *
     * @param jwt token
     * @return parseJWT
     * @throws Exception
     */
    public static Claims parseJWT(String jwt) throws Exception {
    
    
        SecretKey secretKey = generalKey();
        return Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(jwt)
                .getBody();
    }
	//测试生成Token
    public static void main(String[] args) {
    
    
        String jwt = JwtUtil.createJWT("1", "3333", null);
        System.out.println(jwt);
    }
}

LoginAop拦截:

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
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.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * @author zhu
 * @date 2021/7/28 15:22
 * Aop 登录拦截器
 */
@Slf4j
@Aspect
@Component
public class HttpAspect {
    
    

    /**
     * 登录路径 ->放行
     */
    private static final String LOGIN = "login";

    /**
     * @Pointcut 声明切入点表达式。
     * 注意此处扫描的是你的Controller层接口位置
     */
    @Pointcut("execution(public * com.zhu.controller..*..*(..))")
    public void pointcut() {
    
    
    }

    /**
     * @Around 环绕通知
     * @Around("pointcut()") 可以理解为对这个方法进行环绕通知
     * ProceedingJoinPoint 参数 用于环绕通知,
     * 使用proceed()方法来执行目标方法,可以理解为 前置通知结束 开始执行使用该注解的方法。
     */
    @Around("pointcut()")
    public Object doBefore(ProceedingJoinPoint joinPoint) throws Throwable {
    
    
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        String token = request.getHeader("Authorization");
        if (request.getRequestURI().contains(LOGIN)) {
    
    
            return joinPoint.proceed();
        }
  
        if (StringUtils.isNotBlank(token)) {
    
    
            try {
    
    
                JwtUtil.parseJWT(token);
            } catch (Exception e) {
    
    
                // 解析jwt令牌出错, 说明令牌过期或者伪造等不合法情况出现 401
                log.info("AuthorizeFilter  解析jwt令牌出错", e);
                //此处可以返回自定义 Result结果对象 转成Json格式
                return JsonUtil.format("解析jwt令牌出错");
            }
        } else {
    
    
            log.info("AuthorizeFilter  登录令牌不存在");   
            return JsonUtil.format(" 登录令牌不存在");
        }
        //执行业务逻辑,放行
        return joinPoint.proceed();
    }
}

四、PostMan使用:

Postman

登录接口应该放行So:
在这里插入图片描述

Guess you like

Origin blog.csdn.net/weixin_48134878/article/details/119910162