基于Spring Boot + Nacos + Dubbo自定義鑒權(quán)過濾器實現(xiàn)方案解析
實現(xiàn)說明
整體流程:
- 服務提供者啟動時會注冊到 Nacos,并啟用自定義的
AuthFilter - 客戶端調(diào)用服務前,通過
RpcContext設置鑒權(quán)信息(token 和應用名) - 服務端的
AuthFilter會攔截請求,驗證鑒權(quán)信息 - 驗證通過則繼續(xù)調(diào)用,否則拋出異常
- 服務提供者啟動時會注冊到 Nacos,并啟用自定義的
關鍵實現(xiàn)點:
- 使用
@Activate注解指定過濾器在服務端生效 - 通過 SPI 機制注冊過濾器
- 在
invoke方法中實現(xiàn)鑒權(quán)邏輯 - 利用
RpcContext傳遞和獲取調(diào)用上下文信息
- 使用
動態(tài)配置:
- 進階實現(xiàn)中添加了 Nacos 配置中心客戶端
- 可以動態(tài)獲取和更新鑒權(quán)規(guī)則,無需重啟服務
使用時,需要先啟動 Nacos 服務器,然后分別啟動服務提供者和消費者,即可看到鑒權(quán)效果。你可以根據(jù)實際業(yè)務需求修改validateToken和hasMethodPermission方法中的鑒權(quán)邏輯。
1.自定義鑒權(quán)過濾器實現(xiàn)
package com.example.dubbo.filter;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import org.springframework.stereotype.Component;
/**
* 基于Dubbo SPI的自定義鑒權(quán)過濾器
*/
@Activate(group = CommonConstants.PROVIDER, order = 100) // 僅在服務端生效
@Component
public class AuthFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
// 1. 從上下文獲取調(diào)用信息
RpcContext context = RpcContext.getContext();
String token = context.getAttachment("auth_token");
String appName = context.getAttachment("app_name");
String clientIp = context.getRemoteHost();
String methodName = invocation.getMethodName();
// 2. 打印調(diào)用信息
System.out.println("收到調(diào)用請求 - 方法: " + methodName + ", 客戶端IP: " + clientIp + ", 應用名: " + appName);
// 3. 執(zhí)行鑒權(quán)邏輯
if (!validateToken(token, appName)) {
throw new RpcException("鑒權(quán)失敗: 無效的token或應用名");
}
// 4. 檢查方法級權(quán)限
if (!hasMethodPermission(appName, methodName)) {
throw new RpcException("權(quán)限不足: 應用" + appName + "沒有調(diào)用" + methodName + "方法的權(quán)限");
}
// 5. 鑒權(quán)通過,繼續(xù)執(zhí)行調(diào)用
return invoker.invoke(invocation);
}
/**
* 驗證token有效性
*/
private boolean validateToken(String token, String appName) {
// 實際項目中,這里應該從Nacos配置中心或數(shù)據(jù)庫獲取有效token列表
// 簡單示例:驗證token格式和應用名
if (token == null || appName == null) {
return false;
}
// 從Nacos獲取配置的有效應用和token映射關系
// 這里簡化處理,實際應通過NacosConfigService獲取
return "valid_token_123".equals(token) && "authorized_app".equals(appName);
}
/**
* 檢查是否有方法調(diào)用權(quán)限
*/
private boolean hasMethodPermission(String appName, String methodName) {
// 實際項目中,這里應該從Nacos配置中心獲取應用與方法的權(quán)限映射
// 簡單示例:只有特定應用可以調(diào)用敏感方法
if ("deleteUser".equals(methodName) && !"admin_app".equals(appName)) {
return false;
}
return true;
}
}2.創(chuàng)建 SPI 配置文件,讓 Dubbo 能夠發(fā)現(xiàn)我們的過濾器:
# 注冊自定義鑒權(quán)過濾器 authFilter=com.example.dubbo.filter.AuthFilter
3.服務提供者配置
application.yml
spring:
application:
name: dubbo-auth-provider
dubbo:
application:
name: dubbo-auth-provider
registry:
address: nacos://127.0.0.1:8848 # Nacos注冊中心地址
username: nacos # Nacos用戶名
password: nacos # Nacos密碼
protocol:
name: dubbo
port: 20880
provider:
filter: authFilter # 啟用自定義鑒權(quán)過濾器
timeout: 3000
# Nacos配置中心
nacos:
config:
server-addr: 127.0.0.1:8848
namespace: public4.服務接口和實現(xiàn)
package com.example.dubbo.service;
public interface UserService {
String getUserInfo(Long id);
String deleteUser(Long id);
}
package com.example.dubbo.service.impl;
import com.example.dubbo.service.UserService;
import org.apache.dubbo.config.annotation.DubboService;
@DubboService(interfaceClass = UserService.class)
public class UserServiceImpl implements UserService {
@Override
public String getUserInfo(Long id) {
return "User info for id: " + id + ", name: testUser";
}
@Override
public String deleteUser(Long id) {
return "User " + id + " deleted successfully";
}
}服務消費者配置和代碼
package com.example.dubbo.consumer;
import com.example.dubbo.service.UserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.rpc.RpcContext;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class ConsumerApplication {
@DubboReference
private UserService userService;
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
@Bean
public ApplicationRunner runner() {
return args -> {
// 調(diào)用前設置鑒權(quán)信息
RpcContext.getContext()
.setAttachment("auth_token", "valid_token_123")
.setAttachment("app_name", "authorized_app");
// 調(diào)用普通方法
String userInfo = userService.getUserInfo(1L);
System.out.println("調(diào)用結(jié)果: " + userInfo);
// 嘗試調(diào)用需要管理員權(quán)限的方法
try {
String deleteResult = userService.deleteUser(1L);
System.out.println("刪除結(jié)果: " + deleteResult);
} catch (Exception e) {
System.out.println("調(diào)用deleteUser方法失敗: " + e.getMessage());
}
};
}
}從 Nacos 配置中心獲取鑒權(quán)規(guī)則
package com.example.dubbo.config;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
import java.util.concurrent.Executor;
@Configuration
public class NacosConfig {
@Value("${nacos.config.server-addr}")
private String serverAddr;
@Value("${nacos.config.namespace}")
private String namespace;
@Bean
public ConfigService configService() throws NacosException {
Properties properties = new Properties();
properties.put("serverAddr", serverAddr);
properties.put("namespace", namespace);
ConfigService configService = NacosFactory.createConfigService(properties);
// 監(jiān)聽鑒權(quán)規(guī)則配置變化
String dataId = "dubbo-auth-rules";
String group = "DEFAULT_GROUP";
configService.addListener(dataId, group, new Listener() {
@Override
public void receiveConfigInfo(String configInfo) {
System.out.println("收到新的鑒權(quán)規(guī)則配置: " + configInfo);
// 更新本地緩存的鑒權(quán)規(guī)則
AuthRuleCache.updateRules(configInfo);
}
@Override
public Executor getExecutor() {
return null;
}
});
// 初始化加載配置
String config = configService.getConfig(dataId, group, 5000);
if (config != null) {
AuthRuleCache.updateRules(config);
}
return configService;
}
}
// 鑒權(quán)規(guī)則緩存類
class AuthRuleCache {
private static String authRules;
public static void updateRules(String rules) {
authRules = rules;
// 這里可以解析規(guī)則并存儲到內(nèi)存中
}
public static String getAuthRules() {
return authRules;
}
}到此這篇關于基于 Spring Boot + Nacos + Dubbo 的完整自定義鑒權(quán)過濾器實現(xiàn)方案的文章就介紹到這了,更多相關springboot nacos dubbo自定義鑒權(quán)過濾器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
解決IDEA報錯Caused by: org.springframework.boot.web.se
遇到IDEA啟動報錯,可嘗試以下方法:打開項目設置(Ctrl+Shift+Alt+S),將JDK版本修改為1.8;或者檢查TomCat依賴,若有問題可嘗試刪除,此外,確保每次拉取項目后,maven地址設置為本地,并且JDK版本設置為1.8,以上為個人解決經(jīng)驗,希望對大家有所幫助2024-09-09
java編程創(chuàng)建型設計模式工廠方法模式示例詳解
這篇文章主要為大家介紹了java編程創(chuàng)建型設計模式之工廠方法模式的創(chuàng)建及案例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-02-02
Java中DTO與Entity拷貝轉(zhuǎn)換的方法小結(jié)
在?Java?開發(fā)中,DTO(Data?Transfer?Object)和?Entity(實體類)是常見的兩種數(shù)據(jù)模型,本文將介紹幾種常見的工具類和自定義方式來實現(xiàn)這種轉(zhuǎn)換,感興趣的可以了解下2025-02-02
SpringMVC+ZTree實現(xiàn)樹形菜單權(quán)限配置的方法
本篇文章主要介紹了SpringMVC+ZTree實現(xiàn)樹形菜單權(quán)限配置的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-12-12

