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

如何实现仅在指定静态IP下运行的Flutter应用并限制异IP联网?

需求可行性与实现方案

可行性结论

这个需求完全可行,核心逻辑是检测设备当前网络的IP地址,仅当与指定静态IP匹配时,才允许应用发起网络请求;不匹配时拦截所有请求并限制功能。


具体实现步骤

1. 获取设备当前网络IP地址

需根据需求区分局域网静态IP或公网静态IP,采用对应获取方式:

场景1:限制局域网静态IP

使用network_info_plus包获取设备本地局域网IP:

  • 在pubspec.yaml添加依赖:
dependencies:
  network_info_plus: ^4.0.1
  • 编写IP获取方法:
import 'package:network_info_plus/network_info_plus.dart';

Future<String?> getCurrentLocalIp() async {
  final networkInfo = NetworkInfo();
  // 获取WiFi连接下的局域网IP
  final wifiIp = await networkInfo.getWifiIP();
  
  // 移动网络下的本地IP需通过原生API额外处理
  return wifiIp;
}

注意:iOS 13+获取WiFi IP需定位权限,需在Info.plist添加NSLocationWhenInUseUsageDescription;Android需在AndroidManifest.xml添加ACCESS_WIFI_STATE权限。

场景2:限制公网静态IP

通过请求外部接口获取设备公网IP(如http://icanhazip.com),需在IP校验前发起请求:

import 'package:http/http.dart' as http;

Future<String?> getCurrentPublicIp() async {
  try {
    final response = await http.get(Uri.parse("http://icanhazip.com"));
    if (response.statusCode == 200) {
      return response.body.trim();
    }
  } catch (_) {}
  return null;
}

2. 全局拦截网络请求

通过统一网络客户端拦截所有请求,仅允许IP匹配时发起请求,推荐使用dio拦截器方案:

  • 添加dio依赖:
dependencies:
  dio: ^5.3.2
  • 自定义IP校验拦截器:
import 'package:dio/dio.dart';

class IpRestrictionInterceptor extends Interceptor {
  final String allowedIp;

  IpRestrictionInterceptor(this.allowedIp);

  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
    // 根据需求选择获取本地IP或公网IP
    final currentIp = await getCurrentLocalIp(); 
    
    if (currentIp == allowedIp) {
      // IP匹配,放行请求
      handler.next(options);
    } else {
      // IP不匹配,拦截请求并返回错误
      handler.reject(DioException(
        requestOptions: options,
        error: "当前网络IP不符合要求,无法访问互联网",
        type: DioExceptionType.cancel,
      ));
    }
  }
}
  • 初始化Dio时绑定拦截器:
final dio = Dio();
// 替换为你的指定静态IP
dio.interceptors.add(IpRestrictionInterceptor("192.168.1.100"));

若使用原生http包,可封装自定义客户端:

import 'package:http/http.dart' as http;

class IpRestrictedClient extends http.BaseClient {
  final http.Client _innerClient = http.Client();
  final String allowedIp;

  IpRestrictedClient(this.allowedIp);

  @override
  Future<http.StreamedResponse> send(http.BaseRequest request) async {
    final currentIp = await getCurrentLocalIp();
    if (currentIp == allowedIp) {
      return _innerClient.send(request);
    } else {
      throw Exception("当前网络IP不符合要求,无法访问互联网");
    }
  }
}

3. 应用启动与实时状态监听

  • 启动时直接校验IP,不符合则显示限制页面:
import 'package:flutter/material.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  const allowedIp = "192.168.1.100";
  final currentIp = await getCurrentLocalIp();

  runApp(MaterialApp(
    home: currentIp == allowedIp ? const HomePage() : const RestrictedPage(),
  ));
}

class RestrictedPage extends StatelessWidget {
  const RestrictedPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text("当前网络环境不符合要求,无法使用应用"),
      ),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("主页面")),
      body: const Center(child: Text("正常使用中")),
    );
  }
}
  • 监听网络状态变化,实时更新IP校验状态:
    使用connectivity_plus包监听网络切换,重新校验IP并更新界面:
dependencies:
  connectivity_plus: ^5.0.1
class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  late StreamSubscription<ConnectivityResult> _connectivitySubscription;
  const allowedIp = "192.168.1.100";
  bool _isIpValid = true;

  @override
  void initState() {
    super.initState();
    _connectivitySubscription = Connectivity().onConnectivityChanged.listen((result) async {
      final currentIp = await getCurrentLocalIp();
      setState(() {
        _isIpValid = currentIp == allowedIp;
      });
    });
  }

  @override
  void dispose() {
    _connectivitySubscription.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (!_isIpValid) {
      return const RestrictedPage();
    }
    return Scaffold(
      appBar: AppBar(title: const Text("主页面")),
      body: const Center(child: Text("正常使用中")),
    );
  }
}

4. 额外安全建议

  • 双重校验:服务器端同步添加IP白名单校验,防止客户端被篡改绕过。
  • 代码混淆:对Flutter代码进行混淆,提升逆向破解难度。
  • 动态配置:通过远程配置中心动态获取允许的IP,避免频繁打包发布。

内容的提问来源于stack exchange,提问作者mohammad aslam ansari

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 15:35:36