Higress WASM插件开发实战:用Rust构建API网关认证插件

还在为API网关的认证功能发愁?一文教你用Rust快速开发Higress WASM插件,实现强大的基础认证功能!

【免费下载链接】higress Next-generation Cloud Native Gateway | 下一代云原生网关 【免费下载链接】higress 项目地址: https://gitcode.com/GitHub_Trending/hi/higress

读完本文你将掌握:

  • ✅ WASM插件开发环境搭建
  • ✅ Rust语言基础插件编写
  • ✅ 认证逻辑实现技巧
  • ✅ 插件部署与测试方法

环境准备与项目结构

首先确保你的开发环境满足以下要求:

# 安装Rust和WASI目标
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup target add wasm32-wasip1

Higress的WASM插件开发框架位于plugins/wasm-rust/目录,结构清晰:

wasm-rust/
├── src/              # SDK核心库
├── extensions/       # 插件示例
├── example/          # 完整示例
└── Makefile          # 构建脚本

插件开发架构

创建基础认证插件

extensions/目录下创建新插件:

cd plugins/wasm-rust/
mkdir extensions/basic-auth
cd extensions/basic-auth

创建Cargo.toml配置文件:

[package]
name = "basic-auth"
version = "0.1.0"
edition = "2021"
publish = false

[lib]
crate-type = ["cdylib"]

[dependencies]
higress-wasm-rust = { path = "../../", version = "0.1.0" }
proxy-wasm = { git="https://github.com/higress-group/proxy-wasm-rust-sdk", branch="main", version="0.2.2" }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
base64 = "0.21"  # 用于Base64解码

实现认证逻辑

创建src/lib.rs文件,实现基础认证功能:

use higress_wasm_rust::*;
use proxy_wasm::traits::*;
use proxy_wasm::types::*;
use serde::{Deserialize, Serialize};
use base64::prelude::*;

// 插件配置结构
#[derive(Default, Clone, Serialize, Deserialize)]
struct BasicAuthConfig {
    username: String,
    password: String,
    realm: String,
}

// 根上下文
struct BasicAuthRoot {
    log: Log,
    rule_matcher: SharedRuleMatcher<BasicAuthConfig>,
}

impl BasicAuthRoot {
    fn new() -> Self {
        Self {
            log: Log::new("basic-auth".to_string()),
            rule_matcher: Rc::new(RefCell::new(RuleMatcher::new())),
        }
    }
}

impl Context for BasicAuthRoot {}
impl RootContext for BasicAuthRoot {
    fn on_configure(&mut self, plugin_configuration_size: usize) -> bool {
        on_configure(self, plugin_configuration_size, 
                    &mut self.rule_matcher.borrow_mut(), &self.log)
    }

    fn create_http_context(&self, context_id: u32) -> Option<Box<dyn HttpContext>> {
        Some(Box::new(BasicAuth {
            log: self.log.clone(),
            rule_matcher: self.rule_matcher.clone(),
        }))
    }

    fn get_type(&self) -> Option<ContextType> {
        Some(ContextType::HttpFilter)
    }
}

// HTTP上下文处理
struct BasicAuth {
    log: Log,
    rule_matcher: SharedRuleMatcher<BasicAuthConfig>,
}

impl Context for BasicAuth {}

impl HttpContext for BasicAuth {
    fn on_http_request_headers(&mut self, num_headers: usize, end_of_stream: bool) -> HeaderAction {
        self.log.info("Checking basic authentication");
        
        // 获取Authorization头
        if let Some(auth_header) = self.get_http_request_header("Authorization") {
            if auth_header.starts_with("Basic ") {
                let encoded = &auth_header[6..];
                if let Ok(decoded) = BASE64_STANDARD.decode(encoded) {
                    if let Ok(credentials) = String::from_utf8(decoded) {
                        let parts: Vec<&str> = credentials.split(':').collect();
                        if parts.len() == 2 {
                            let username = parts[0];
                            let password = parts[1];
                            
                            // 获取配置进行验证
                            if let Some(config) = self.get_config() {
                                if username == config.username && password == config.password {
                                    self.log.info("Authentication successful");
                                    return HeaderAction::Continue;
                                }
                            }
                        }
                    }
                }
            }
        }
        
        // 认证失败
        self.log.warn("Authentication failed");
        self.send_http_response(
            401,
            vec![
                ("WWW-Authenticate", &format!("Basic realm=\"{}\"", self.get_realm())),
                ("Content-Type", "text/plain"),
            ],
            Some(b"Authentication required"),
        );
        HeaderAction::Pause
    }
    
    fn get_config(&self) -> Option<BasicAuthConfig> {
        // 从规则匹配器获取配置
        let matcher = self.rule_matcher.borrow();
        matcher.get_match_config(self).cloned()
    }
    
    fn get_realm(&self) -> String {
        self.get_config()
            .map(|config| config.realm)
            .unwrap_or_else(|| "Restricted Area".to_string())
    }
}

proxy_wasm::main! {|_| -> Box<dyn RootContext> {
    Box::new(BasicAuthRoot::new())
}}

构建与测试

使用Makefile构建插件:

# 在plugins/wasm-rust/目录下执行
make build PLUGIN_NAME=basic-auth

构建成功后会在extensions/basic-auth/目录生成plugin.wasm文件。

部署配置

创建Kubernetes配置部署插件:

apiVersion: extensions.higress.io/v1alpha1
kind: WasmPlugin
metadata:
  name: basic-auth
  namespace: higress-system
spec:
  selector:
    matchLabels:
      higress: higress-system-higress-gateway
  defaultConfig:
    username: "admin"
    password: "secret123"
    realm: "API Gateway"
  url: file:///path/to/plugin.wasm

验证功能

测试认证功能:

# 未认证访问
curl http://your-gateway/api/protected

# 使用正确凭据
curl -H "Authorization: Basic YWRtaW46c2VjcmV0MTIz" http://your-gateway/api/protected

认证流程

最佳实践与进阶功能

  1. 安全增强:在实际生产环境中,建议:

    • 使用环境变量注入密码
    • 集成外部认证服务
    • 添加速率限制防止暴力攻击
  2. 性能优化

    • 使用缓存机制减少重复认证
    • 优化Base64解码性能
    • 合理设置日志级别
  3. 扩展功能

    • 支持多用户认证
    • 添加JWT令牌验证
    • 集成OAuth2.0协议

总结

通过本文,你已经掌握了使用Rust开发Higress WASM认证插件的基本技能。WASM插件为API网关提供了强大的扩展能力,而Rust语言的内存安全特性确保了插件的稳定性。

下一步学习建议:

三连支持:点赞👍 + 收藏⭐ + 关注👀 下期预告:《Higress插件性能优化实战》!

【免费下载链接】higress Next-generation Cloud Native Gateway | 下一代云原生网关 【免费下载链接】higress 项目地址: https://gitcode.com/GitHub_Trending/hi/higress

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值