java aop拦截器

2023-10-30

可在切面代码修改为数据库获取或redis中获取

依赖

 <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.22</version>
        </dependency>

自定义注解

package com.ekkcole.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/***样例数据 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiCommon {
}

AOP切面代码

package com.ekkcole.aspects;

import cn.hutool.core.date.DateUtil;
import com.ekkcole.utils.CommUtils;
import com.ekkcole.utils.CommonDateUtil;
import com.ekkcole.utils.MD5Utils;
import lombok.AllArgsConstructor;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.util.Date;

import static java.time.LocalDate.now;

/**
 * 对使用ApiCommon注解实现切面
 * @author 曹猛
 */
@Aspect
@Component
@AllArgsConstructor
public class ApiSignAspectSection {

	private static final String SIGN_NAME = "signName";
	private static final String ACCESS_KEY = "accessKey";
	private static final String DATA_TAMP = "datatamp";
	private static final String SECURITY_KEY = "securityKey";
	private static final String NEW_SIGN_NAME = "AJGOJEW098823gajgjoa8u982GOAJOG";
	private static final String NEW_ACCESS_KEY = "ALGNJHO883989GS;Z;KJIGJIDDS883LSJLA";
	private static final Integer LENGTH = 13;

	/**
	 * 切面,只对使用了ApiCommon注解的接口生效
	 */
	@Pointcut(value = "@annotation(com.ekkcole.annotation.ApiCommon)")
	public void cutPoint() {
	}

	@Around("cutPoint()")
	public Object arround(ProceedingJoinPoint pjp) throws Throwable {
		HttpServletRequest request =  ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		// 签名
		String signName = null;
		// 秘钥
		String accessKey = null;
		// 时间戳
		String datatamp = null;
		// 安全秘钥加密后由signName-accessKey 经过MD5加密后得到
		String securityKey = null;
		if (!CommUtils.isEmpty(request.getHeader(SIGN_NAME))) {
			signName = request.getHeader(SIGN_NAME);
		}
		if (!CommUtils.isEmpty(request.getHeader(ACCESS_KEY))) {
			accessKey = request.getHeader(ACCESS_KEY);
		}
		if (!CommUtils.isEmpty(request.getHeader(DATA_TAMP))) {
			datatamp = request.getHeader(DATA_TAMP);
		}
		if (!CommUtils.isEmpty(request.getHeader(SECURITY_KEY))) {
			securityKey = request.getHeader(SECURITY_KEY);
		}
		if (CommUtils.isEmpty(signName) || CommUtils.isEmpty(accessKey)) {
			throw new RuntimeException("签名或秘钥不可为空");
		}
		if (!NEW_SIGN_NAME.equals(signName) && !NEW_ACCESS_KEY.equals(accessKey)) {
			throw new RuntimeException("验证失败,请检查签名或秘钥是否正确");
		}
		// 传入的签名与秘钥拼接与安全密钥加密验证
		String md5TextKey = signName + "-" + accessKey;
		// 判断安全秘钥加密是否为空
		if (CommUtils.isEmpty(securityKey)) {
			throw new RuntimeException("安全密钥不可为空");
		}
		// 验证加密秘钥是否正确
		if (!MD5Utils.valid(md5TextKey, securityKey)) {
			throw new RuntimeException("安全密钥验证失败");
		}
		if (CommUtils.isEmpty(datatamp)) {
			throw new RuntimeException("时间戳不可为空");
		}
		if (datatamp.length() != LENGTH) {
			throw new RuntimeException("时间戳错误,请传入毫秒级的时间戳");
		}
		//验证时间戳是否在有效的范围内
		Date time = CommonDateUtil.stampToDate(datatamp);
		//计算日期差,传入的时间与当前时间相比较,获取差值
		long diff = Math.abs(CommonDateUtil.diff(new Date(), time, CommonDateUtil.MINUTE_MS));
		if (diff < 0 || diff > 5) {
			throw new RuntimeException("已过期,请更新时间戳");
		}
		return pjp.proceed();
	}

}

工具类

MD5工具

package com.ekkcole.utils;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * MD5加密/验证工具类
 */
public class MD5Utils {
    static final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
    static final char hexDigitsLower[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    /**
     * 对字符串 MD5 无盐值加密
     *
     * @param plainText 传入要加密的字符串
     * @return MD5加密后生成32位(小写字母 + 数字)字符串
     */
    public static String MD5Lower(String plainText) {
        try {
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest md = MessageDigest.getInstance("MD5");

            // 使用指定的字节更新摘要
            md.update(plainText.getBytes());

            // digest()最后确定返回md5 hash值,返回值为8位字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符
            // BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值。1 固定值
            return new BigInteger(1, md.digest()).toString(16);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 对字符串 MD5 加密
     *
     * @param plainText 传入要加密的字符串
     * @return MD5加密后生成32位(大写字母 + 数字)字符串
     */
    public static String MD5Upper(String plainText) {
        try {
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest md = MessageDigest.getInstance("MD5");

            // 使用指定的字节更新摘要
            md.update(plainText.getBytes());

            // 获得密文
            byte[] mdResult = md.digest();
            // 把密文转换成十六进制的字符串形式
            int j = mdResult.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = mdResult[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];// 取字节中高 4 位的数字转换, >>> 为逻辑右移,将符号位一起右移
                str[k++] = hexDigits[byte0 & 0xf]; // 取字节中低 4 位的数字转换
            }
            return new String(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 对字符串 MD5 加盐值加密
     *
     * @param plainText 传入要加密的字符串
     * @param saltValue 传入要加的盐值
     * @return MD5加密后生成32位(小写字母 + 数字)字符串
     */
    public static String MD5Lower(String plainText, String saltValue) {
        try {
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest md = MessageDigest.getInstance("MD5");

            // 使用指定的字节更新摘要
            md.update(plainText.getBytes());
            md.update(saltValue.getBytes());

            // digest()最后确定返回md5 hash值,返回值为8位字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符
            // BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值。1 固定值
            return new BigInteger(1, md.digest()).toString(16);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 对字符串 MD5 加盐值加密
     *
     * @param plainText 传入要加密的字符串
     * @param saltValue 传入要加的盐值
     * @return MD5加密后生成32位(大写字母 + 数字)字符串
     */
    public static String MD5Upper(String plainText, String saltValue) {
        try {
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest md = MessageDigest.getInstance("MD5");

            // 使用指定的字节更新摘要
            md.update(plainText.getBytes());
            md.update(saltValue.getBytes());

            // 获得密文
            byte[] mdResult = md.digest();
            // 把密文转换成十六进制的字符串形式
            int j = mdResult.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = mdResult[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * MD5加密后生成32位(小写字母+数字)字符串
     * 同 MD5Lower() 一样
     */
    public final static String MD5(String plainText) {
        try {
            MessageDigest mdTemp = MessageDigest.getInstance("MD5");

            mdTemp.update(plainText.getBytes("UTF-8"));

            byte[] md = mdTemp.digest();
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigitsLower[byte0 >>> 4 & 0xf];
                str[k++] = hexDigitsLower[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 校验MD5码
     *
     * @param text 要校验的字符串
     * @param md5  md5值
     * @return 校验结果
     */
    public static boolean valid(String text, String md5) {
        return md5.equals(MD5(text)) || md5.equals(MD5(text).toUpperCase());
    }

}

时间工具

package com.ekkcole.utils;

import cn.hutool.core.date.DateUtil;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

/**
 * 通用工具类
 *
 * @author Chill
 */
public class CommonDateUtil {
	private  final static String FIRST="1";
	private final  static String SECOND="2";
	private final  static String THIRD="3";
	private final static String FOUR="4";

	/** 毫秒 */
	private final static long MS = 1;
	/** 每秒钟的毫秒数 */
	private final static long SECOND_MS = MS * 1000;
	/** 每分钟的毫秒数 */
	public final static long MINUTE_MS = SECOND_MS * 60;


	/**
	 * 字符串转换数字
	 *
	 * @param id
	 * @return
	 */
	public static Integer parseInt(String id) {
		Integer uId = 0;

		if (id == null || "".equals(id))
			return -1;

		try {
			uId = Integer.parseInt(id);
		} catch (NumberFormatException e) {
			// e.printStackTrace();
			uId = -1;
		}

		return uId;
	}


	/**
	 * LocalDateTime 转换为 Date
	 *
	 * @param localDateTime
	 * @return
	 */
	public static Date LocalDateTimeToDate(LocalDateTime localDateTime) {
		ZoneId zone = ZoneId.systemDefault();
		Instant instant = localDateTime.atZone(zone).toInstant();
		return Date.from(instant);
	}

	/**
	 * Date 转换为 LocalDateTime
	 *
	 * @param date
	 * @return
	 */
	public static LocalDateTime DateToLocalDateTime(Date date) {
		Instant instant = date.toInstant();
		ZoneId zone = ZoneId.systemDefault();
		return LocalDateTime.ofInstant(instant, zone);
	}

	/**
	 * 解析字符串格式的时间
	 * @param date
	 * @return
	 */
	public static Map<String, Object> parseDateStr(String date) {
		Objects.requireNonNull(date);

		Map<String, Object> dateMap = new HashMap<>();
		String[] values = date.split(",");
		if (values != null && values.length == 2) {
			String begin = values[0].trim();
			if (begin != null && begin.length() >= 10)
				begin = begin.substring(0, 10);
			dateMap.put("begin", begin);

			String end = values[1].trim();
			if (end != null && end.length() >= 10)
				end = end.substring(0, 10);
			dateMap.put("end", end);
		}
		return dateMap;
	}

	/**
	 * 获取对象的所有属性,包括从父类继承的属性
	 *
	 * @param obj
	 * @param parent
	 * @return
	 */
	public static Field[] getFields(Object obj, boolean parent) {
		Objects.requireNonNull(obj);

		List<Field> fieldList = new ArrayList<>();
		Class<? extends Object> clazz = obj.getClass();

		while (clazz != null) {
			fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
			clazz = parent ? clazz.getSuperclass() : null;
		}

		Field[] fields = new Field[fieldList.size()];
		return fieldList.toArray(fields);
	}

	/**
	 * 验证字符串是否为空
	 *
	 * @param value
	 * @return
	 */
	public static boolean notEmpty(String value) {
		return value != null && !"".equals(value);
	}

	/**
	 * 首字母转换为大写
	 *
	 * @param fieldName
	 * @return
	 */
	public static String capitalize(String fieldName) {
		String getName = "";
		if (notEmpty(fieldName)) {
			getName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
		}

		return getName;
	}
	

	public static Date strToDate(String dateStr, String format) {
		Date date = new Date();
		if (dateStr != null) {
			try {
				SimpleDateFormat sdf = new SimpleDateFormat(format);
				date = sdf.parse(dateStr);
			} catch (ParseException e) {
				date = new Date();
			}
		}
		return date;
	}

	public static String parseDateStr(Date date, String format) {
		String dateStr = "";
		if (date != null) {
			SimpleDateFormat sdf = new SimpleDateFormat(format);
			dateStr = sdf.format(date);
		}
		return dateStr;
	}


	/**
	 * 计算日期差
	 * @param subtrahend
	 * @param minuend
	 * @param diffField
	 * @return
	 */
	public static long diff(Date subtrahend, Date minuend, long diffField) {
		long diff = minuend.getTime() - subtrahend.getTime();
		return diff / diffField;
	}
	/**
	 * 将时间戳变为日期
	 * @param s
	 * @return
	 */
	public static Date stampToDate(String s){
		String res;
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		long lt = new Long(s);
		Date date = new Date(lt);
		res = simpleDateFormat.format(date);
		return DateUtil.parse(res, "yyyy-MM-dd HH:mm:ss");
	}
}

测试

在这里插入图片描述
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java aop拦截器 的相关文章

随机推荐

  • 深入学习jquery源码之Deferred对象与holdReady()

    深入学习jquery源码之Deferred对象与holdReady jQuery的Deferred对象也有resolve reject then方法 还有done fail always 方法 jQuery就是用这个Deferred对象来注
  • 超级计算机使用机时,使用天河二号超级计算机资源申请表(10页).doc

    使用天河二号超级计算机资源申请表 10页 使用天河二号超级计算机资源申请表 Tianhe 2 Supercomputer Resource Application Form 填表日期 年 月 日 Date of Application 单位
  • 盛高会员系统服务器启动不了,盛高会员管理系统实用操作指南

    一 盛高小小系列软件介绍 二 盛高会员管理系统操作指引 1 安装盛高会员管理系统软件 单机应用须安装数据服务器和软件客户端 局域网应用主机安装数据服务器和客户端 分机只安装客户端 互联网应用总部安装数据服务器和客户端 分店分机只安装客户端
  • 数据分析实战(二) 基于美国人口adult数据集R语言分析实战

    目录 一 数据集介绍 二 数据预处理 三 描述型统计分析 四 机器学习及模型比较 一 数据集介绍 数据来源于UCI数据库 网址为adult数据集 下载下来是dat文件 可以用txt文本打开 该数据集共32560条数据 15个变量 具体变量名
  • #python 输入三条边的长度,判断这几条边是否能组成三角形

    python 输入三条边的长度 判断这几条边是否能组成三角形 问题描述 输入三角形的三条边 判断该三角形的形状 周长 面积和每条边的高 第一步 导入所需要的库math import math 第二步 判断此三条线段是否能组成三角形 判断条件
  • JSP数据交互(一)---内置对象》application:

    JSP数据交互 一 内置对象 application application实现用户之间的数据共享 application对象常用方法 applicatiion常用方法 方法名称 说明 void 色图Attribute String key
  • pandas读取Excel file

    Pandas read excel 参数 pandas read excel io sheet name 0 header 0 names None index col None usecols None squeeze False dty
  • Oracle + MyBatis 3 实现批量新增/修改

    批量新增Mapper 定义 public interface BaseHouseMapper 批量新增Mapper 定义 void batchInsert Param list List
  • git 查看该项目在git的具体地址

    在终端输入如下命令 git remote v 结果如下 上图显示的是该项目的git地址
  • 【Python】Pycharm连接云服务器的MySQL数据库详细步骤

    Pycharm连接数据库 MySQL 云服务器 准备阶段 pycharm的配置 服务器配置 问题汇总 准备阶段 准备阶段 pycharm正确运行环境 服务器一枚 pycharm直接官网下载 我是用的2020 3 2版本 服务器是腾讯云的免费
  • 关于android的WebView

    android webkit库聚合了webkit内核的浏览器功能 webview就是她的一个控件 可以使得网页轻松的内嵌到app里 并且比较强大的是 还可以直接跟js相互调用 webview有两个方法 setWebChromeClient和
  • flutter设置状态栏颜色

    Android flutter SystemUiOverlayStyle systemUiOverlayStyle SystemUiOverlayStyle statusBarColor Colors transparent SystemC
  • C语言程序设计之猜数字游戏(随机数的讲解)

    游戏玩法 电脑随机生成一个随机数 1 100之间 玩家根据提示进行猜测 直到猜对为止 相关知识点 分支与循环 随机数的生成 时间戳 标准输入输出 强制类型转换等 时间戳和随机数的生成将在本篇blog中重点讲解 其他知识点在其他blog中有重
  • 关于视频自动截取封面_ ffmpeg

    后台富文本框内 插入视频后 保存信息时 对视频封面处理 ffmpeg下载地址 创建bat文件 如以下关于bat文件的内容 start C Users 83469 Desktop ffmpeg 20180310 2536bd8 win64 s
  • Android 虚拟机简单介绍——ART、Dalvik、启动流程分析

    Android 虚拟机方面的知识 我是通过 深入理解 Android 内核设计思想 来学习的 内容特别多 只有一章 但有 160 页 感觉和 Android 开发有些偏 因此很多内容都没有认真去看 比如 EFL 格式等 这里只是选取了一些感
  • 尝试CornerNet-Lite进行目标识别并嵌入ROS

    CornerNet Lite是刚开源不久的实时目标检测方法 据说比YOLO3 牛逼 于是打算尝鲜一波 首先说运行的环境要求 1 Python 3 7 2 PyTorch 1 0 0 3 CUDA 10 意思是你得有一张NVIDIA的显卡 比
  • 10款最好用的代码编辑器 你是用哪种登录酷游?

    你是学习程式语言的初学者吗 本文由酷游登录网址AP98点NE 原创 未经许可请勿转发 可能刚学会第一门代码语言 或是厌倦了当前的代码编辑器 想改换一款介面美观又好用 以下将整理5款我们认为好用的代码编辑器 也欢迎各位分享自己正在使用的咯 1
  • 在Ubuntu上使用NFS挂载

    假设要把192 16 2 101服务器上的 home sharedata 挂载到192 16 2 102服务器上的 home receive data 一 服务端 1 安装NFS服务端 sudo apt get install nfs ke
  • 结合分析和数值技术 Python 在基本力学应用

    特点 展示了如何将分析方法和数值方法无缝集成来解决物理问题 内容 介绍 开始编程 单位和测量 一维运动 一维力 二维和三维运动 二维和三维力 受限运动 力和约束运动 工作能量 动量 脉冲和碰撞 多粒子系统 旋转运动 刚体的旋转 刚体动力学
  • java aop拦截器

    可在切面代码修改为数据库获取或redis中获取 依赖