SpringAOP之日志和身份验证

日志

1、定义日志接口

import java.lang.annotation.*;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnnotation {String type() default "";String module() default "";String content() default "";
}

2、定义日志切面类

@Aspect
@Component
public class LogAspect {@Autowiredprivate LogService logService;@Pointcut("@annotation(com.nudt.annotation.LogAnnotation)")public void logPointCut() {}@Around("logPointCut()")public Object around(ProceedingJoinPoint point) throws Throwable {long beginTime = System.currentTimeMillis();//执行方法Object result = point.proceed();//执行时长(毫秒)long time = System.currentTimeMillis() - beginTime;//保存日志saveLog(point, (int) time);return result;}private void saveLog(ProceedingJoinPoint joinPoint, int time) {MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();Log log = new Log();LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);if (logAnnotation != null) {//注解上的描述log.setOperation(logAnnotation.content());}//请求的方法名String className = joinPoint.getTarget().getClass().getName();String methodName = signature.getName();log.setMethod(className + "." + methodName + "()");//请求的参数Object[] args = joinPoint.getArgs();try {String params = new Gson().toJson(args[0]);log.setParams(params);} catch (Exception e) {}HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();HttpSession session = request.getSession();//获取登录名String loginName = (String) session.getAttribute("loginName");//获取客户端ipString clientIp = IPUtil.getClientIp();//获取服务端ipString serverIp = IPUtil.getServerIp();}}

3、使用

 @GetMapping@LogAnnotation(module="登录",content="用户登录",type="1")public String login(){}

验证

1、定义验证接口

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validate {String value() default "";
}

2、定义验证切面类

@Aspect
@Component
public class ValidateAspect {@Pointcut("@annotation(com.nudt.annotation.Validate)")public void validatePointCut() {}@Before("validatePointCut()")public void before(JoinPoint joinPoint) throws Exception{int status = IPUtil.getStatus();if(status==0){throw new ValidationException("未登录");}if(status==1){throw new ValidationException("无权限");}}
}

3、使用

@GetMapping@Validatepublic String del(){}

工具类:获取服务器和客户端ip,以及在session中获取信息

public class IPUtil {private static final Logger log = LoggerFactory.getLogger(IPUtil.class);//获取服务器ippublic static String getServerIp() {try{InetAddress localhost = InetAddress.getLocalHost();return localhost.getHostAddress();}catch(UnknownHostException e){throw new RuntimeException(e);}}//获取客户端ippublic static String getClientIp() {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();String ip = request.getHeader("x-forwarded-for");log.info("x-forwarded-for ip:{}",ip);if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("Proxy-Client-IP");log.info("Proxy-Client-IP ip:{}",ip);}if (StringUtils.isBlank(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("WL-Proxy-Client-IP");log.info("WL-Proxy-Client-IP ip:{}",ip);}if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("HTTP_CLIENT_IP");log.info("HTTP_CLIENT_IP ip:{}",ip);}if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("HTTP_X_FORWARDED_FOR");log.info("HTTP_X_FORWARDED_FOR ip:{}",ip);}if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();log.info("remote ip:{}",ip);}if(StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip) && StringUtils.contains(ip,",")){//多次反向代理后会有多个ip值,第一个为真实ipip = StringUtils.substringBefore(ip,",");}String tempIp = null;if(StringUtils.isNotBlank(ip) && !"unknown".equalsIgnoreCase(ip) && StringUtils.contains(ip,",")){String[] ips = StringUtils.split(ip, ",");for(String ip1:ips){if(!isInnerIp(ip1.trim())){tempIp = ip1.trim();break;}//如果多ip都是内网ip,则取第一个ipif(null == tempIp){tempIp = ips[0].trim();}ip = tempIp;}}if(ip !=null && ip.contains("unknown")){ip = ip.replaceAll("unknown","");ip = ip.trim();}//处理localhostif(StringUtils.isBlank(ip) || !"unknown".equalsIgnoreCase(ip) || StringUtils.split(ip,",").length!=4){try{InetAddress inetAddress = InetAddress.getLocalHost();ip = inetAddress.getHostAddress();log.info("getHostAddress ip:{}",ip);}catch(UnknownHostException e){throw new RuntimeException(e);}}return ip;}private static boolean isInnerIp(String ipAddress) {boolean isInnerIp;long ipNum = getIpNum(ipAddress);
//        私有ip:A类   10.0.0.0~10.255.255.255
//               B类   172.16.0.0~172.31.255.255
//               C类   192.168.0.0~192.168.255.255long aBegin = getIpNum("10.0.0.0");long aEnd = getIpNum("10.255.255.255");long bBegin = getIpNum("172.16.0.0");long bEnd = getIpNum("172.31.255.255");long cBegin = getIpNum("192.168.0.0");long cEnd = getIpNum("192.168.255.255");isInnerIp = isInner(ipNum,aBegin,aEnd) || isInner(ipNum,bBegin,bEnd) || isInner(ipNum,cBegin,cEnd);return isInnerIp;}private static boolean isInner(long ipNum, long begin, long end){return (ipNum >= begin) && (ipNum <= end);}private static long getIpNum(String ipAddress) {String[] ips = StringUtils.split(ipAddress,",");long a = Integer.parseInt(ips[0]);long b = Integer.parseInt(ips[1]);long c = Integer.parseInt(ips[2]);long d = Integer.parseInt(ips[3]);return a*256*256*256 + b*256*256 + c*256 + d;}public static int getStatus() {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();HttpSession session = request.getSession();//获取登录名String token = (String) session.getAttribute("token");Map<String, String> map = JwtUtil.parseJWT(token);String status = map.get("type");if(status.equals("0")){return 0;}if(status.equals("1")){return 1;}return 2;}
}

工具类:jwt相关

public class JwtUtil {//设置过期时间private static final long EXPIRE_TIME = 240 * 60 * 1000;//token秘钥private static final String TOKEN_SECRET = "f26e587c28064d0e855e72c0a6a0e618";public static String sign(String username, String type) {String token = "";try {//过期时间Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);//秘钥及加密算法Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);//设置头部信息Map<String, Object> header = new HashMap<>(2);header.put("typ", "JWT");header.put("alg", "HS256");//携带username,password信息,生成签名return JWT.create().withHeader(header).withClaim("loginName", username).withClaim("type", type).withExpiresAt(date).sign(algorithm);} catch (Exception e) {e.printStackTrace();return null;}}public 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);return true;}catch (Exception e){e.printStackTrace();return false;}}public static Map<String, String> parseJWT(String token){/*** @desc   解密token,返回一个map* @params [token]需要校验的串**/DecodedJWT decodeToken = JWT.decode(token);Map<String, String> map = new HashMap<>();map.put("loginName",decodeToken.getClaim("loginName").asString());map.put("type",decodeToken.getClaim("type").asString());return map;}public static boolean isJwtExpired(String token){/*** @desc 判断token是否过期* @author lj*/try {DecodedJWT decodeToken = JWT.decode(token);return decodeToken.getExpiresAt().before(new Date());} catch(Exception e){return true;}}public static void main(String[] args) {String username ="zhangsan";String password = "123";String token = sign(username,password);System.out.println(token);boolean b = verify(token);System.out.println(b);}

引入依赖

<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.8.3</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>

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

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

相关文章

《计算机组成及汇编语言原理》阅读笔记:p177-p177

《计算机组成及汇编语言原理》学习第 13 天&#xff0c;p177-p177 总结&#xff0c;总计 1 页。 一、技术总结 1.real mode A programming model where the program has access to the entire capability of the machine, bypassing security and memory management. Useful…

珞珈一号夜光遥感数据地理配准,栅格数据地理配准

目录 一、夜光数据下载&#xff1a; 二、夜光遥感数据地理配准 三、计算夜光数据值 四、辐射定标 五、以表格显示分区统计 五、结果验证 夜光数据位置和路网位置不匹配&#xff0c;虽然都是WGS84坐标系&#xff0c;不匹配&#xff01;&#xff01;&#xff01;不要看到就直接…

python学习笔记—12—

1. 布尔类型 (1) 定义 (2) 比较运算符 (3) 代码演示 1. 手动定义 bool_1 True bool_2 False print(f"bool_1的内容是&#xff1a;{bool_1}, 类型是&#xff1a;{type(bool_1)}") print(f"bool_2的内容是&#xff1a;{bool_2}, 类型是&#xff1a;{type(bool…

Redis 使用redisTemplate获取某个规则下的key的全量数据(示例Set结构)

如下是redis中存储的数据结构 我想取key以favorites:结尾的所有数据 Redis 的 SCAN 命令用于迭代数据库中的键&#xff0c;支持通过模式过滤结果。模式规则基于 Redis 的通配符匹配语法&#xff0c;类似于文件名匹配规则&#xff1a; *&#xff1a;匹配零个或多个字符。?&…

CertiK《Hack3d:2024年度安全报告》(附报告全文链接)

CertiK《Hack3d&#xff1a;2024年度安全报告》现已发布&#xff0c;本次报告深入分析了2024年Web3.0领域的安全状况。2024年损失总额超过23亿美元&#xff0c;同比增幅高达31.61%&#xff1b;其中&#xff0c;12月的损失金额最少。过去一年&#xff0c;网络钓鱼攻击和私钥泄露…

AI知识库与用户行为分析:优化用户体验的深度洞察

在当今数字化时代&#xff0c;用户体验&#xff08;UX&#xff09;已成为衡量产品成功与否的关键指标之一。AI知识库作为智能客服系统的重要组成部分&#xff0c;不仅为用户提供快速、准确的信息检索服务&#xff0c;还通过用户行为分析&#xff0c;为产品优化提供了深度洞察。…

Vue3 + ElementPlus动态合并数据相同的单元格(超级详细版)

最近的新项目有个需求需要合并单元列表。ElementPlus 的 Table 提供了合并行或列的方法&#xff0c;可以参考一下https://element-plus.org/zh-CN/component/table.html 但项目中&#xff0c;后台数据返回格式和指定合并是动态且没有规律的&#xff0c;Element 的示例过于简单&…

CSS进阶和SASS

目录 一、CSS进阶 1.1、CSS变量 1.2、CSS属性值的计算过程 1.3、做杯咖啡 1.4、下划线动画 1.5、CSS中的混合模式(Blending) 二、SASS 2.1、Sass的颜色函数 2.2、Sass的扩展(extend)和占位符(%)、混合(Mixin) 2.3、Sass的数学函数 2.4、Sass的模块化开发 2.5、Sass…

概率论与数理统计

概率论占比更多&#xff0c;三分之二左右 数理统计会少一些 事件之间的概率 ab互斥&#xff0c;不是ab独立 古典概型吃高中基础&#xff0c;考的不会很多 条件概率公式&#xff0c;要记 公式不要全记&#xff0c;很多有名称的公式是通过基础公式转换而来的 目的在于解决一…

javaEE-多线程进阶-JUC的常见类

juc:指的是java.util.concurrent包&#xff0c;该包中加载了一些有关的多线程有关的类。 目录 一、Callable接口 FutureTask类 参考代码&#xff1a; 二、ReentrantLock 可重入锁 ReentrantLock和synchronized的区别&#xff1a; 1.ReentantLock还有一个方法&#xff1a…

智慧工地系统:建筑施工智能化管理的全新模式

智慧工地概述 智慧工地是将互联网的理念和和物联网的技术引入建筑工地&#xff0c;依托物联网、互联网、大数据、5G技术&#xff0c;建立云端数据平台&#xff0c;形成大数据的业务体系&#xff0c;打通一线操作与远程监管的链条&#xff0c;实现劳务、安全、环境、材料等各个…

FastAPI 统一接口响应(Json)模板的使用示例

目录 FastAPI 统一接口响应&#xff08;Json&#xff09;模板的使用示例 实际案例 实现方法 1. 创建统一响应格式的中间件 2. 将中间件添加到 FastAPI 应用中 3. 解释代码 4. 扩展和定制 5. 测试 FastAPI 统一接口响应&#xff08;Json&#xff09;模板的使用示例 实际…

Linux平台下实现的小程序-进度条

目录 1.换行、回车概念 2.缓冲区 2.1缓冲区 2.2强制刷新 3.进度条程序 Makefile文件 ProgressBar.h ProgressBar.c Main.c 执行结果 1.换行、回车概念 /n&#xff1a;换行回车&#xff08;\r&#xff1a;回车&#xff09; 2.缓冲区 如下图在vim编辑器中的命令模式下…

C++ 基础思维导图(一)

目录 1、C基础 IO流 namespace 引用、const inline、函数参数 重载 2、类和对象 类举例 3、 内存管理 new/delete 对象内存分布 内存泄漏 4、继承 继承权限 继承中的构造与析构 菱形继承 1、C基础 IO流 #include <iostream> #include <iomanip> //…

Java - 日志体系_Apache Commons Logging(JCL)日志接口库_桥接Logback 及 源码分析

文章目录 PreApache CommonsApache Commons ProperLogging &#xff08;Apache Commons Logging &#xff09; JCL 集成logbackPOM依赖配置文件 logback.xml使用 源码分析jcl-over-slf4j 的工作原理1. LogFactory 的实现2. SLF4JLogFactory 和 Log 的实例化过程3. SLF4JLog 和 …

中小企业如何进行数字化转型?

​在这个日新月异的数字时代&#xff0c;企业数字化转型已成为不可逆转的潮流与战略选择。大数据、云计算、人工智能、物联网等前沿科技正重塑着各行各业的面貌。面对激烈的市场竞争和不断变化的客户需求&#xff0c;中小企业作为国民经济的重要组成部分&#xff0c;数字化转型…

闪存知识科普-基本储存单元结构

概述&#xff1a; 闪存&#xff0c;即FlashMemory。其基本储存单元&#xff08;Memory Cell&#xff09;如下图所示。看起来有点像N沟道&#xff08;N-Channel&#xff09;MOS管&#xff0c;但比MOS管多一个悬浮闸&#xff08;Floating Gate&#xff09;。悬浮闸内可以储存电荷…

[江科大STM32] 第五集快速建立STM32工程模板——笔记

保存&#xff0c;进去选芯片型号&#xff0c;我们是F10C8T6 一个MD&#xff0c;还有所有.c.h 这里所有文件 这里所有文件

Elasticsearch:基础概念

一、什么是Elasticsearch Elasticsearch是基于 Apache Lucene 构建的分布式搜索和分析引擎、可扩展数据存储和矢量数据库。它针对生产规模工作负载的速度和相关性进行了优化。使用 Elasticsearch 可以近乎实时地搜索、索引、存储和分析各种形状和大小的数据。Elasticsearch 是…

安卓播放器TVbox或影视仓软件如何链接到xiaoya小雅超集?很详细的教程

前言 这里咱们说的安卓播放器软件指的是这个&#xff1a; 还有这个&#xff1a; 这两个软件只是个壳&#xff0c;你需要做的仅仅是把需要的内容填写到对应的位置即可。 开始这个教程之前&#xff0c;你需要先部署好小雅&#xff0c;如果没有部署小雅&#xff0c;这个教程基本…