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

.NET MAUI应用全局网络请求白名单过滤及iOS代理集成求助

解决方案:.NET 8 MAUI 全局HTTPS请求白名单实现

针对你的敏感信息处理MAUI应用,以下是分平台的全局白名单拦截方案,以及替代实现方式:

一、Android平台:全局OkHttp拦截器

MAUI在Android上默认采用OkHttp作为HttpClient后端,通过全局替换Handler实现透明拦截:

1. 自定义白名单拦截器(Kotlin)

在Android项目中创建拦截器类:

class WhitelistInterceptor : Interceptor {
    private val allowedDomains = setOf("example.com", "example01.com")

    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()
        val host = request.url.host.lowercase()
        
        // 支持子域名匹配(如api.example.com)
        val isAllowed = allowedDomains.any { host.endsWith(it) }
        
        if (!isAllowed) {
            throw IOException("Unauthorized domain: $host")
        }
        
        return chain.proceed(request)
    }
}

2. 全局配置HttpClient(C#)

在Android项目的MainApplication.cs中替换默认Handler:

protected override void OnCreate()
{
    base.OnCreate();
    var okHttpClient = new OkHttpClient.Builder()
        .AddInterceptor(new WhitelistInterceptor())
        .Build();
    HttpMessageHandlerProvider.SetHandler(() => new OkHttpMessageHandler(okHttpClient));
}

该方案会拦截所有通过HttpClient发起的请求(包括NuGet包内的请求)。

二、iOS平台:集成Network Extension代理

你已创建的NEAppProxyProvider可按以下步骤与MAUI集成:

1. 配置权限与App Groups

在iOS项目的Info.plist中添加VPN权限与Extension配置:

<key>NSExtension</key>
<dict>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.networkextension.app-proxy</string>
    <key>NSExtensionPrincipalClass</key>
    <string>$(PRODUCT_MODULE_NAME).AppProxyProvider</string>
</dict>
<key>NSVPNUsageDescription</key>
<string>需通过VPN过滤未授权网络请求</string>

在Xcode中为主应用和Extension添加相同的App Group(如group.com.yourcompany.yourapp),用于共享白名单配置。

2. MAUI中启动代理(C#)

在iOS项目的工具类中添加启动代理的代码:

using NetworkExtension;

public static async Task StartProxy()
{
    var manager = new NEAppProxyManager();
    var config = new NEAppProxyProviderConfig();
    config.AppBundleIdentifier = "com.yourcompany.yourapp.networkextension"; // 你的Extension Bundle ID
    config.ServerAddress = "127.0.0.1";
    config.ServerPort = 8080;
    
    // 写入白名单到App Groups
    var userDefaults = new NSUserDefaults("group.com.yourcompany.yourapp", NSUserDefaultsType.SuiteName);
    userDefaults.SetStringArray(new[] {"example.com", "example01.com"}, "AllowedDomains");
    userDefaults.Synchronize();
    
    await manager.LoadFromPreferencesAsync();
    if (manager.Configuration == null) await manager.SaveToPreferencesAsync();
    await manager.StartTunnelAsync();
}

3. Extension中实现过滤(Swift)

在AppProxyProvider中读取白名单并拦截请求:

class AppProxyProvider: NEAppProxyProvider {
    private var allowedDomains: Set<String> = []
    
    override func startProxy(options: [String : Any]?, completionHandler: @escaping (Error?) -> Void) {
        if let userDefaults = UserDefaults(suiteName: "group.com.yourcompany.yourapp"),
           let domains = userDefaults.stringArray(forKey: "AllowedDomains") {
            allowedDomains = Set(domains)
        }
        completionHandler(nil)
    }
    
    override func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool {
        guard let tcpFlow = flow as? NEAppProxyTCPFlow,
              let remoteHost = tcpFlow.remoteHost,
              let remotePort = tcpFlow.remotePort else {
            flow.closeReadWrite()
            return false
        }
        
        // 仅过滤HTTPS请求(443端口)
        if remotePort == 443 {
            let host = remoteHost.lowercased()
            let isAllowed = allowedDomains.contains { host.hasSuffix($0) }
            if !isAllowed {
                flow.closeReadWrite()
                return false
            }
        }
        
        // 转发合法请求到目标服务器
        let connection = NWConnection(host: NWEndpoint.Host(remoteHost), port: NWEndpoint.Port(rawValue: remotePort)!, using: .tcp)
        connection.stateUpdateHandler = { state in
            switch state {
            case .ready: tcpFlow.open(with: connection)
            default: flow.closeReadWrite()
            }
        }
        connection.start(queue: .global())
        return true
    }
}

注意:iOS需用户手动授权VPN,且需在App Store Connect配置Network Extension权限才能通过审核。

三、跨平台替代方案:全局HttpClient工厂替换

若无需VPN,可通过自定义IHttpClientFactory强制所有请求使用白名单拦截器:

在MauiProgram.cs中配置:

builder.Services.AddHttpClient("WhitelistedClient")
    .AddHttpMessageHandler<WhitelistHandler>();

// 替换默认HttpClientFactory
builder.Services.AddSingleton<IHttpClientFactory, WhitelistedHttpClientFactory>();

实现拦截器与工厂类:

public class WhitelistHandler : DelegatingHandler
{
    private readonly HashSet<string> _allowedDomains = new() { "example.com", "example01.com" };

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var host = request.RequestUri?.Host?.ToLower();
        if (host == null || !_allowedDomains.Any(d => host.EndsWith(d)))
        {
            throw new HttpRequestException($"Unauthorized domain: {host}");
        }
        return await base.SendAsync(request, cancellationToken);
    }
}

public class WhitelistedHttpClientFactory : IHttpClientFactory
{
    private readonly IHttpClientFactory _innerFactory;

    public WhitelistedHttpClientFactory(IHttpClientFactory innerFactory)
    {
        _innerFactory = innerFactory;
    }

    public HttpClient CreateClient(string name)
    {
        return _innerFactory.CreateClient("WhitelistedClient");
    }
}

局限性:仅能拦截通过IHttpClientFactory创建的请求,无法处理直接new HttpClient()的代码。

额外安全建议

  • 白名单域名硬编码并通过代码混淆加密,防止被篡改
  • 定期扫描NuGet依赖,检测恶意代码
  • 启用MAUI代码签名与应用加固,防止篡改

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 21:46:12