You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust实现局域网设备IP发现:优先返回200响应并验证JWT

Rust局域网设备IP发现与JWT验证实现方案

需求梳理

你需要实现一个局域网扫描函数,完成以下目标:

  • 对192.168.0.0/24网段的所有IP发送GET http://{ip}:8000/ping请求
  • 一旦收到状态码200的响应,立即返回该IP并终止所有未完成的请求
  • 验证响应返回的JWT令牌,确保目标设备合法

现有代码问题

当前代码仅异步spawn了所有请求,但没有处理响应、没有等待任务完成,也没有实现终止机制和JWT验证逻辑。我们需要基于tokio和reqwest完善这些功能,同时引入JWT验证库。

实现步骤与完整代码

1. 添加依赖

首先在Cargo.toml中添加所需依赖:

[dependencies]
tokio = { version = "1.0", features = ["full"] }
reqwest = { version = "0.11", features = ["json"] }
jsonwebtoken = "9.0"
serde = { version = "1.0", features = ["derive"] }
thiserror = "1.0"

2. 完整实现代码

use jsonwebtoken::{decode, DecodingKey, Validation};
use reqwest::Client;
use serde::Deserialize;
use thiserror::Error;
use tokio::task::JoinSet;

// 定义自定义错误类型
#[derive(Error, Debug)]
pub enum DiscoveryError {
    #[error("HTTP请求错误: {0}")]
    ReqwestError(#[from] reqwest::Error),
    #[error("JWT验证失败: {0}")]
    JwtError(#[from] jsonwebtoken::errors::Error),
    #[error("未找到合法设备")]
    NoDeviceFound,
}

// 定义JWT的Payload结构,根据实际需求调整字段
#[derive(Debug, Deserialize)]
struct JwtPayload {
    // 示例:设备标识,可根据实际情况添加其他声明(如exp过期时间)
    device_id: String,
    exp: usize, // 过期时间戳,建议验证该字段
}

async fn discover() -> Result<String, DiscoveryError> {
    // 创建可复用的HTTP客户端,避免重复建立连接
    let client = Client::new();
    // 管理所有异步任务,支持取消未完成任务
    let mut tasks = JoinSet::new();

    // 遍历网段内所有IP
    for i in 0..256 {
        let client = client.clone();
        tasks.spawn(async move {
            let ip = format!("192.168.0.{i}");
            let url = format!("http://{ip}:8000/ping");

            // 发送请求,设置超时避免长时间等待
            match client.get(&url).timeout(std::time::Duration::from_secs(2)).await {
                Ok(response) => {
                    if response.status().is_success() {
                        // 读取响应体中的JWT令牌
                        let jwt_token = response.text().await?;
                        // 验证JWT
                        validate_jwt(&jwt_token)?;
                        Ok(ip)
                    } else {
                        Err(DiscoveryError::NoDeviceFound)
                    }
                }
                Err(_) => Err(DiscoveryError::NoDeviceFound),
            }
        });
    }

    // 等待任务完成,一旦找到合法设备就终止所有任务
    while let Some(result) = tasks.join_next().await {
        match result {
            Ok(Ok(ip)) => {
                // 取消所有未完成的任务
                tasks.shutdown().await;
                return Ok(ip);
            }
            // 忽略单个任务的错误,继续等待其他任务
            _ => continue,
        }
    }

    // 所有任务完成都未找到合法设备
    Err(DiscoveryError::NoDeviceFound)
}

// JWT验证函数,需替换为实际的秘钥和验证规则
fn validate_jwt(token: &str) -> Result<(), jsonwebtoken::errors::Error> {
    // 替换为你的实际秘钥,建议从环境变量读取,不要硬编码
    let secret = b"your-secret-key-here";
    let decoding_key = DecodingKey::from_secret(secret);
    // 配置验证规则,默认会验证exp字段
    let validation = Validation::default();

    // 解码并验证JWT
    let _payload: JwtPayload = decode(token, &decoding_key, &validation)?;

    // 如果需要额外验证逻辑(比如device_id是否符合预期),可以在这里添加
    // if payload.device_id != "expected-device-id" {
    //     return Err(jsonwebtoken::errors::Error::InvalidToken);
    // }

    Ok(())
}

#[tokio::main]
async fn main() {
    match discover().await {
        Ok(ip) => println!("找到合法设备: {}", ip),
        Err(e) => println!("发现失败: {}", e),
    }
}

关键实现细节

  • 并发任务管理:使用tokio::task::JoinSet来管理所有扫描任务,一旦找到符合条件的设备,调用shutdown()立即终止所有未完成的任务,避免不必要的网络请求。
  • 请求超时:给每个HTTP请求设置超时(示例中为2秒),防止单个无响应的IP阻塞整个扫描流程。
  • JWT验证:通过jsonwebtoken库验证令牌的签名和声明(默认验证exp过期时间),确保返回令牌的合法性,防范伪造设备或中间人攻击。
  • 错误处理:自定义错误类型,清晰区分不同类型的错误,便于调试和处理。

内容的提问来源于stack exchange,提问作者Murad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 21:15:47