【PmHub后端篇】PmHub中基于自定义注解和AOP的服务接口鉴权与内部认证实现

1 引言

在现代软件开发中,尤其是在微服务架构下,服务接口的鉴权和内部认证是保障系统安全的重要环节。本文将详细介绍PmHub中如何利用自定义注解和AOP(面向切面编程)实现服务接口的鉴权和内部认证,所涉及的技术知识点对于理解和实现系统安全具有重要意义。

2 注解的基本概念

在Java中,注解(Annotation)是一种特殊的语法,以@符号开头,是Java 5开始引入的新特性。注解可看作特殊的注释,用于修饰类、方法或变量,为程序在编译或运行时提供信息。例如JDK内置的@Override注解,用于帮助编译器检查方法是否正确重写父类方法。

package java.lang;import java.lang.annotation.*;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

2.1 注解的作用

  1. 编译时检查:如@Override注解辅助编译器检查方法重写的正确性。
  2. 代码生成:像@Entity注解可告知框架生成对应的数据库表。
  3. 运行时处理@Deprecated注解在运行时提醒开发者某方法或类已不建议使用。

2.2 注解的解析方法

  1. 编译期直接扫描:编译器编译Java代码时扫描注解并处理,如@Override注解的处理。
  2. 运行时通过反射处理:Spring框架中的@Value@Component等注解通过反射处理,也是自定义注解常用的解析方式。

3 自定义注解的实现

自定义注解主要包括以下几个步骤:

  • 定义注解:使用@interface关键字定义注解。
  • 注解元素:在注解中定义元素,就像在接口中定义方法。
  • 元注解:使用元注解(如@Retention@Target等)来描述注解的行为。

3.1 定义注解

使用@interface关键字定义注解,例如:

import java.lang.annotation.*;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {String value() default "";int number() default 0;
}

在上面的例子中,MyAnnotation注解有两个元素:valuenumber。其中,number有一个默认值0。

3.2 元注解

元注解用于描述注解本身的行为,常见元注解有:
@Retention:指明注解的保留策略。
@Target:指明注解的使用目标。

  1. @Retention:指定注解的生命周期,取值包括:
    • RetentionPolicy.SOURCE:注解只在源代码中存在,编译后消失。
    • RetentionPolicy.CLASS:注解在编译后存在于.class文件中,运行时不存在。
    • RetentionPolicy.RUNTIME:注解在运行时存在,可通过反射读取。
  2. @Target:指定注解的使用目标,常见取值有:
    • ElementType.TYPE:用于类、接口、枚举、注解类型。
    • ElementType.FIELD:用于字段或属性。
    • ElementType.METHOD:用于方法。
    • ElementType.PARAMETER:用于参数。
    • ElementType.CONSTRUCTOR:用于构造函数。
    • ElementType.LOCAL_VARIABLE:用于局部变量。

3.3 自定义注解示例

下面是一个包含@Retention和@Target元注解的完整自定义注解示例:

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;// 定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {String value();int number() default 0;
}

3.4 使用自定义注解

定义完注解后,可以在代码中使用它:

public class Test {@MyAnnotation(value = "Test method", number = 42)public void testMethod() {// 方法的具体实现}
}

3.5 通过反射读取注解

import java.lang.reflect.Method;public class Main {public static void main(String[] args) throws Exception {Method method = Test.class.getMethod("testMethod");if (method.isAnnotationPresent(MyAnnotation.class)) {MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);System.out.println("Value: " + annotation.value());System.out.println("Number: " + annotation.number());}}
}

4 Spring AOP简介

AOP(面向切面编程)是一种编程范式,允许在不改变业务逻辑代码的情况下,将横切关注点(如日志记录、事务管理、安全检查等)模块化。Spring AOP提供了多种定义和使用切面的方式:

  1. 注解:使用@Aspect和相关注解(如@Before@After@Around等)定义切面和切点。
  2. XML配置:在Spring配置文件中定义切面和切点,但现代开发中较少使用。

5 微服务架构下的鉴权基础

微服务架构由多个独立服务组成,服务间通讯、监控等聚合而成。其优点包括提高开发效率、增强可维护性、灵活技术选型、支持持续交付和部署、实现故障隔离、按需扩展等。

鉴权是对权限认证和授权控制,专业的鉴权框架有Spring Security和Shiro等。常见鉴权方式有:

  1. 用户名和密码:传统鉴权方式,需注意密码存储和传输安全。
  2. 多因素认证(MFA):通过多种验证因素确认用户身份,如知识因子、拥有因子、生物因子。
  3. OAuth(开放授权):允许第三方应用以有限权限访问用户资源,常用于社交登录和API访问控制。
  4. JWT(JSON Web Token):基于JSON的开放标准,用于各方之间传递声明,包含用户信息和签名,可用于鉴权和授权,PmHub采用此方式鉴权。

6 PmHub中的鉴权认证实现

6.1 PmHub架构

PmHub采用微服务架构,有单独的认证服务pmhub-auth。请求分为通过API网关的请求和微服务内部请求
在这里插入图片描述

6.2 PmHub中的认证

PmHub 采用微服务架构,其认证流程如下:

  1. 登录请求转发
    用户发起登录请求,该请求先到达网关(如端口 8080 )。网关根据配置的路由规则,将请求转发到认证中心服务pmhub - auth(如端口 6800 ) 。
  2. 用户信息查询
    认证服务接收到登录请求后,依据用户输入的用户名,查询对应的用户信息。
  3. 密码校验
    从Redis中获取密码相关信息(文中未明确密码存入Redis的过程,但逻辑上是从中获取用于校验 ),对用户输入的密码进行正确性校验。
  4. 记录登录日志
    若密码校验通过,认证服务记录此次登录日志,留存登录相关信息。
  5. 生成登录token
    认证服务生成JWT(JSON Web Token)字符串作为登录token ,JWT中包含用户信息、签名等内容。
  6. 存储token至Redis
    将生成的JWT字符串存入Redis,并设置过期时间,以此维护用户登录状态及确定过期时间。
  7. 返回token信息
    认证服务将生成的token信息返回给客户端。后续客户端携带该token进行请求时,系统会先去Redis检查JWT字符串是否存在,若存在则对其进行解析,能成功解析则认定用户已登录且身份合法 。

在这里插入图片描述

6.3 PmHub中的鉴权

6.3.1 外部请求

请求到达网关后,通过微服务的自定义请求头拦截器(放置在公共包,各服务可引用),配合自定义注解和AOP,拦截请求头获取用户和权限信息,有权限则放行,无权限则抛出异常。
在这里插入图片描述

6.3.2 内部请求

正常情况下内部请求无需鉴权,可以直接处理。但使用OpenFeign时,数据都是通过接口暴露出去的,为防止外部请求调用接口,采用自定义内部请求注解,AOP控制拦截,然后在内部请求调用的时候,额外加一个头字段加以区分。

PmHub做内部请求鉴权流程如下:

  1. 自定义注解
    定义内部认证注解InnerAuth ,使用@Target(ElementType.METHOD)指定该注解用于方法上,@Retention(RetentionPolicy.RUNTIME)表示注解在运行时存在,可通过反射读取。注解包含元素isUser() ,用于标识是否校验用户信息,默认值为false 。代码如下:
/*** 内部认证注解*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InnerAuth {/*** 是否校验用户信息*/boolean isUser() default false;
}
  1. AOP切面控制
    创建InnerAuthAspect类,实现Ordered接口 ,并使用@Aspect@Component注解,将其定义为一个切面并纳入Spring容器管理。通过@Around("@annotation(innerAuth)")定义环绕通知,拦截标注了InnerAuth注解的方法。具体逻辑为:
    • 从请求头中获取FROM_SOURCE字段值,判断是否等于内部请求标识SecurityConstants.INNER ,若不相等,抛出InnerAuthException异常,提示没有内部访问权限。
    • 若配置了需校验用户信息(innerAuth.isUser()true ),从请求头获取用户ID(DETAILS_USER_ID )和用户名(DETAILS_USERNAME ),若二者有空白情况,抛出InnerAuthException异常,提示没有设置用户信息。
    • 若上述校验都通过,执行point.proceed(),放行请求,让目标方法正常执行。

代码如下:

/*** 内部服务调用验证处理*/
@Aspect
@Component
public class InnerAuthAspect implements Ordered {@Around("@annotation(innerAuth)")public Object innerAround(ProceedingJoinPoint point, InnerAuth innerAuth) throws Throwable {String source = ServletUtils.getRequest().getHeader(SecurityConstants.FROM_SOURCE);// 内部请求验证if (!StringUtils.equals(SecurityConstants.INNER, source)) {throw new InnerAuthException("没有内部访问权限,不允许访问");}String userid = ServletUtils.getRequest().getHeader(SecurityConstants.DETAILS_USER_ID);String username = ServletUtils.getRequest().getHeader(SecurityConstants.DETAILS_USERNAME);// 用户信息验证if (innerAuth.isUser() && (StringUtils.isEmpty(userid) || StringUtils.isEmpty(username))) {throw new InnerAuthException("没有设置用户信息,不允许访问 ");}return point.proceed();}
}
  1. OpenFeign请求拦截器处理
    实现feign.RequestInterceptor接口,创建FeignRequestInterceptor类,并使用@Component注解纳入Spring容器管理 。在apply(RequestTemplate requestTemplate)方法中:
    • 获取当前请求HttpServletRequest
    • 从请求头中提取用户ID(DETAILS_USER_ID )、用户密钥(USER_KEY )、用户名(DETAILS_USERNAME )、认证信息(AUTHORIZATION_HEADER )等信息,若存在则设置到RequestTemplate的请求头中,防止用户信息在OpenFeign调用时丢失。
    • 获取客户端IP,通过X-Forwarded-For头字段设置到请求头中。

代码如下:

/*** feign请求拦截器*/
@Component
public class FeignRequestInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate requestTemplate) {HttpServletRequest httpServletRequest = ServletUtils.getRequest();if (StringUtils.isNotNull(httpServletRequest)) {Map<String, String> headers = ServletUtils.getHeaders(httpServletRequest);// 传递用户信息请求头,防止丢失String userId = headers.get(SecurityConstants.DETAILS_USER_ID);if (StringUtils.isNotEmpty(userId)) {requestTemplate.header(SecurityConstants.DETAILS_USER_ID, userId);}String userKey = headers.get(SecurityConstants.USER_KEY);if (StringUtils.isNotEmpty(userKey)) {requestTemplate.header(SecurityConstants.USER_KEY, userKey);}String userName = headers.get(SecurityConstants.DETAILS_USERNAME);if (StringUtils.isNotEmpty(userName)) {requestTemplate.header(SecurityConstants.DETAILS_USERNAME, userName);}String authentication = headers.get(SecurityConstants.AUTHORIZATION_HEADER);if (StringUtils.isNotEmpty(authentication)) {requestTemplate.header(SecurityConstants.AUTHORIZATION_HEADER, authentication);}// 配置客户端IPrequestTemplate.header("X-Forwarded-For", IpUtils.getIpAddr());}}
}

7 总结

本文围绕PmHub展开,介绍了Java注解的概念、实现,Spring AOP的方式。阐述微服务架构下鉴权基础,详细说明PmHub的鉴权认证流程,包括认证、外部及内部请求鉴权,旨在助力开发者理解和实现系统安全功能。

8 参考链接

  1. PmHub自定义注解加 AOP 实现服务接口鉴权和内部认证
  2. 项目仓库(GitHub)
  3. 项目仓库(码云):(国内访问速度更快)

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

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

相关文章

芯片测试之X-ray测试

原理&#xff1a; X-ray是利用阴极射线管产生高能量电子与金属靶撞击&#xff0c;在撞击过程中&#xff0c;因电子突然减速&#xff0c;其损失的动能会以X-Ray形式放出。而对于样品无法以外观方式观测的位置&#xff0c;利用X-Ray穿透不同密度物质后其光强度的变化&#xff0c;…

QBasic 一款古老的编程语言在现代学习中的价值(附程序)

QBasic&#xff08;Quick Beginner’s All-purpose Symbolic Instruction Code&#xff09;是微软公司于 1991 年推出的一款简单易学的编程语言&#xff0c;作为BASIC语言的变种&#xff0c;它曾广泛应用于教育领域和初学者编程入门。尽管在当今Python、Java等现代编程语言主导…

【八股战神篇】Java高频基础面试题

1 面向对象编程有哪些特性&#xff1f; 面向对象编程&#xff08;Object-Oriented Programming&#xff0c;简称 OOP&#xff09;是一种以对象为核心的编程范式&#xff0c;它通过模拟现实世界中的事物及其关系来组织代码。OOP 具有三大核心特性&#xff1a;封装、继承、多态。…

科学养生指南:解锁健康生活新方式

在快节奏的现代生活中&#xff0c;健康养生成为人们关注的焦点。想要拥有良好的身体状态&#xff0c;无需依赖复杂的传统理论&#xff0c;通过科学的生活方式&#xff0c;就能轻松实现养生目标。​ 规律运动是健康的基石。每周进行 150 分钟以上的中等强度有氧运动&#xff0c…

OpenCV阈值处理完全指南:从基础到高级应用

引言 阈值处理是图像处理中最基础、最常用的技术之一&#xff0c;它能够将灰度图像转换为二值图像&#xff0c;为后续的图像分析和处理奠定基础。本文将全面介绍OpenCV中的各种阈值处理方法&#xff0c;包括原理讲解、代码实现和实际应用场景。 一、什么是阈值处理&#xff1…

Java8到24新特性整理

本文整理了 Java 8 至 Java 24 各版本的新特性&#xff0c;内容包括每个版本的新增功能分类&#xff08;如语法增强、性能优化、工具支持等&#xff09;、详细的代码示例&#xff0c;并结合官方文档资料&#xff0c;分析每项特性的应用场景及优缺点。Java 8 发布于 2014 年&…

轮询仲裁器

参考视频 https://www.bilibili.com/video/BV1VQ4y1w7Rr/?spm_id_from333.337.search-card.all.click&vd_sourceaedd69dc9740e91cdd85c0dfaf25304b 算法原理

Armijo rule

非精线搜索步长规则Armijo规则&Goldstein规则&Wolfe规则_armijo rule-CSDN博客 [原创]用“人话”解释不精确线搜索中的Armijo-Goldstein准则及Wolfe-Powell准则 – 编码无悔 / Intent & Focused

力扣HOT100之二叉树:102. 二叉树的层序遍历

这道题太简单了&#xff0c;相当于基础的模板题&#xff0c;但凡涉及到层序遍历一定会用到队列来实现&#xff0c;其他的倒没啥好说的&#xff0c;用两层while循环来层序遍历&#xff0c;外层while循环用于控制访问二叉树的每一层&#xff0c;而内层while循环则负责收割每一层的…

Ubuntu24.04 安装 5080显卡驱动以及cuda

前言 之前使用Ubuntu22.04版本一直报错,然后换了24.04版本才能正常安装 一. 配置基础环境 Linux系统进行环境开发环境配置-CSDN博客 二. 安装显卡驱动 1.安装驱动 按以下步骤来&#xff1a; sudo apt update && sudo apt upgrade -y#下载最新内核并安装 sudo add…

WAS和Tomcat的对比

一、WAS和Tomcat的对比 WebSphere Application Server (WAS) 和 Apache Tomcat 是两款常用的 Java 应用服务器&#xff0c;但它们有许多显著的区别。在企业级应用中&#xff0c;它们扮演不同的角色&#xff0c;各自有其特点和适用场景。以下是它们在多个维度上的详细对比&…

asp.net IHttpHandler 对分块传输编码的支持,IIs web服务器后端技术

IHttpHandler&#xff0c;不支持分块传输编码&#xff08;Chunked Transfer&#xff09;吧&#xff1f; IHttpHandler 对分块传输编码的支持 实际上&#xff0c;IHttpHandler 完全支持分块传输编码&#xff08;Chunked Transfer Encoding&#xff09;&#xff0c;但具体行为取…

为什么elasticsearch配置文件JVM配置31G最佳

Elasticsearch的JVM堆内存配置为32GB被视为最佳实践&#xff0c;主要基于以下综合技术原理和性能优化考量&#xff1a; 1. ‌JVM指针压缩机制优化内存效率‌ 当堆内存≤32GB时&#xff0c;JVM启用‌对象指针压缩&#xff08;Compressed Ordinary Object Pointers, COOP&#…

Systemd基础

1. 概述 Systemd 是一系列工具的集合&#xff0c;其作用也远远不仅是启动操作系统&#xff0c;它还接管了后台服务、结束、状态查询&#xff0c;以及日志归档、设备管理、电源管理、定时任务等许多职责&#xff0c;并支持通过特定事件&#xff08;如插入特定 USB 设备&#xf…

AI预测3D新模型百十个定位预测+胆码预测+去和尾2025年5月16日第79弹

从今天开始&#xff0c;咱们还是暂时基于旧的模型进行预测&#xff0c;好了&#xff0c;废话不多说&#xff0c;按照老办法&#xff0c;重点8-9码定位&#xff0c;配合三胆下1或下2&#xff0c;杀1-2个和尾&#xff0c;再杀6-8个和值&#xff0c;可以做到100-300注左右。 (1)定…

CentOS高手之路:从进阶实战到企业级优化

一、系统深度优化与性能调优 1. 内核参数调优 通过修改/etc/sysctl.conf文件调整内核参数&#xff0c;可显著提升服务器性能。例如&#xff1a; net.ipv4.tcp_fin_timeout30&#xff08;快速释放TCP连接&#xff09; vm.swappiness10&#xff08;减少交换分区使用&#xff0…

Docker 无法拉取镜像解决办法

问题 在linux终端中通过 docker pull 命令拉取镜像&#xff0c;报错无法拉取镜像&#xff0c;这是因为 Docker 客户端无法连接到 Docker 镜像仓库&#xff08;Docker Hub&#xff09; 解决方法 1、配置国内可用的 Docker镜像加速器&#xff0c;这些镜像加速器用于提高从Docke…

【Linux】序列化与反序列化、会话与进程组、守护进程

一.序列化和反序列化 协议其实就是结构化的数据。但是再网络通信中&#xff0c;我们不直接发送结构化的数据给对方。我们一般会将结构化的数据序列化成字符串/字节流&#xff0c;然后通过网络在发送出去。而接收方收到之后&#xff0c;要对收到的字符串/流式数据进行反序列化&…

提权脚本Powerup命令备忘单

1. 获取与加载 从 GitHub 下载&#xff1a;(New-Object Net.WebClient).DownloadFile("https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Privesc/PowerUp.ps1", "C:\Temp\PowerUp.ps1")本地加载&#xff1a;Import-Module .\Power…

2025年Ai写PPT工具推荐,这5款Ai工具可以一键生成专业PPT

上个月给客户做产品宣讲时&#xff0c;我对着空白 PPT 页面熬到凌晨一点&#xff0c;光是调整文字排版就改了十几版&#xff0c;最后还是被吐槽 "内容零散没重点"。后来同事分享了几款 ai 写 PPT 工具&#xff0c;试完发现简直打开了新世界的大门 —— 不用手动写大纲…