【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.pswp.cn/news/905827.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/905827.shtml
英文地址,請注明出處:http://en.pswp.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;試完發現簡直打開了新世界的大門 —— 不用手動寫大綱…