首页 文章

除非我的应用程序批准,否则防止Android手机连接到WiFi网络?

提问于
浏览
17

我想开发一个可以阻止连接到WiFi网络的应用程序,除非我批准它 . 我希望能够查询接入点的MAC地址,并将其与SSID对应的已知地址列表进行比较 . 该应用程序的目标是保护用户免于意外连接到恶意访问点,例如可以使用pineapple devices生成的类型 .

我不清楚我的研究如何实现这一目标 . 问题如How to be notified on wifi network status change?解释了如何检测连接已经发生,但对于我的用例来说已经太晚了 .

ConnectivityManagerWifiManager 似乎都没有提供添加可能会中断正在进行的连接的侦听器的方法 .

我对解决方案的一些想法:

  • 将自己安装为代理,并决定是否允许数据通过 . 但是,这似乎不是基于Do Android proxy settings apply to all apps on the device?的选项(提示:答案是"No") .

  • 用我自己创建的东西替换现有的WiFi管理器 . 但是,我真的很难在Android开发人员指南中找到有关更换系统组件的任何信息 . 因此,我不确定这在非根电话上是否可行 .

  • 将网络密码存储在我的应用程序中,并将WiFi管理器中的密码设置为无意义的值 . 然后捕获一个警告连接失败的广播消息(可能类似于WifiManager.WPS_AUTH_FAILURE)并有选择地决定重新连接回该网络 . 可能是一个可能的(如果丑陋的)解决方案,但是我可以在网络仍然连接时将密码设置回无意义的值,以确保我们不会安静地连接到另一个同名的SSID吗?我不确定 . 我发现菠萝设备可能会接受任何密码,从而使这种方法无效 .

  • 找到一些方法来阻止Android自动连接到已知网络(即之前使用过的网络或者密码存储的网络) . 然后我可以管理我的应用程序的所有连接/断开连接 . 我无法在手机上看到如何手动执行此操作,因此我怀疑这是可行的 .

任何人都可以建议一种可以在非根电话上运行的方法吗?

3 回答

  • 1

    如果不对设备进行root操作,则无法实现非常强大的系统 . 我认为这是你能得到的最接近的:

    或者对于步骤(2),您可以为每个已配置的网络调用disableNetwork(),并根据BSSID选择性地启用它们 . 请注意,MAC地址仍然可以很容易地被欺骗 .

  • 7

    您可以收听wifi的连接变化并对该事件进行操作以启用禁用wifi

    private ConnectivityManager connectionManager;
    boolean previousConnectivityStatus;
    private WifiManager wifiManager;
    
    /* Register Connectivity Receiver */
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
    context.registerReceiver(networkBroadcastReceiver, intentFilter);
    
    /* Register Wifi State Listener */
    IntentFilter wifiStateIntentFilter = new IntentFilter();
    wifiStateIntentFilter.addAction("android.net.wifi.WIFI_STATE_CHANGED");
    context.registerReceiver(wifiStateReceiver, wifiStateIntentFilter);
    
    connectionManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    
    private BroadcastReceiver wifiStateReceiver = new BroadcastReceiver()
    {
        @Override
        public void onReceive(Context context, Intent intent)
        {
            Utility.traceM("NetworkController.wifiStateReceiver.new BroadcastReceiver() {...}::onReceive");
            int extraWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);
            switch (extraWifiState)
                {
                case WifiManager.WIFI_STATE_DISABLED:
                    {
                        Utility.trace("Broadcast Wifi State Disabled");
                        if(isWifiStateEventsEnabled)
                        {
                            EventBus.getDefault().post(new NetworkEvent(NetworkEventType.WIFI_DISABLED));
                        }
                        break;
                    }
                case WifiManager.WIFI_STATE_ENABLED:
                    {
                        Utility.trace("Broadcast Wifi State Enabled");
                        if(isWifiStateEventsEnabled)
                        {
                            EventBus.getDefault().post(new NetworkEvent(NetworkEventType.WIFI_ENABLED));
                        }
                        break;
                    }
                }
        }
    };
    
    private BroadcastReceiver networkBroadcastReceiver = new BroadcastReceiver()
    {
        @Override
        public void onReceive(Context context, Intent intent)
        {
            Utility.traceM("NetworkController.networkBroadcastReceiver.new BroadcastReceiver() {...}::onReceive");
            boolean connectivityStatus = isInternetConnectivityAvailable();
            if (previousConnectivityStatus != connectivityStatus)
            {
                if (connectivityStatus)
                {
                    previousConnectivityStatus = true;
                    Utility.trace("Broadcast Internet Available");
                    EventBus.getDefault().post(new NetworkEvent(NetworkEventType.INTERNET_CONNECTED));
                }
                else
                {
                    previousConnectivityStatus = false;
                    Utility.trace("Broadcast Internet Disconnected");
                    EventBus.getDefault().post(new NetworkEvent(NetworkEventType.INTERNET_DISCONNECTED));
                }
            }
        }
    };
    
  • 1

    如您所知,当连接到Wifi时,sifi管理器应用程序会在连接的Wifi名称下显示提示消息,

    比如连接,验证,获取IP等

    所以我试图搜索如何检测连接到Wifi网络的那些阶段我来回答显示这是如何完成的,它是使用接收器来完成的 SUPPLICANT_STATE_CHANGED_ACTION

    我试图实现它添加代码只是断开连接...这是成功的,因为Wifi从未连接,图标没有出现在通知栏上,日志不断重复这些步骤,虽然有些说它是如何连接的(在日志),但没有任何实际出现在设备本身,所以也许它连接像(10 MS)

    无论如何,下面是我使用的代码:

    public class MyNetworkMonitor extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            // EXTRA_BSSID
            // SUPPLICANT_STATE_CHANGED_ACTION
            // EXTRA_NEW_STATE
    
            // Log.i("YAZAN", intent.getAction() + " " +
            // intent.getStringExtra(WifiManager.EXTRA_BSSID));
            // Log.i("YAZAN", intent.getAction() + " "
            // +intent.getStringExtra(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION));
            // Log.i("YAZAN", intent.getAction() + " "
            // +intent.getStringExtra(WifiManager.EXTRA_NEW_STATE));
    
            //Log.i("YAZAN", intent.getAction() + " " + intent.getStringExtra(WifiManager.EXTRA_BSSID));
    
            String action  = intent.getAction();
            if(action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)){
    
                 WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                Log.d("YAZAN", ">>>>SUPPLICANT_STATE_CHANGED_ACTION<<<<<<");
                SupplicantState supl_state=((SupplicantState)intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE));
    
                switch(supl_state){
                case ASSOCIATED:Log.i("YAZAN", "ASSOCIATED");
                    break;
                case ASSOCIATING:
                    Log.i("YAZAN", "ASSOCIATING");
                     wifi.disconnect();
                     Log.i("YAZAN", "disconnect()");
                    break;
                case AUTHENTICATING:Log.i("YAZAN", "Authenticating...");
                wifi.disconnect();
             Log.i("YAZAN", "disconnect()");
                    break;
                case COMPLETED:Log.i("YAZAN", "Connected");
                    break;
                case DISCONNECTED:Log.i("YAZAN", "Disconnected");
                    break;
                case DORMANT:Log.i("YAZAN", "DORMANT");
                wifi.disconnect();
             Log.i("YAZAN", "disconnect()");
                    break;
                case FOUR_WAY_HANDSHAKE:Log.i("YAZAN", "FOUR_WAY_HANDSHAKE");
                wifi.disconnect();
             Log.i("YAZAN", "disconnect()");
                    break;
                case GROUP_HANDSHAKE:Log.i("YAZAN", "GROUP_HANDSHAKE");
                wifi.disconnect();
             Log.i("YAZAN", "disconnect()");
                    break;
                case INACTIVE:Log.i("YAZAN", "INACTIVE");
                    break;
                case INTERFACE_DISABLED:Log.i("YAZAN", "INTERFACE_DISABLED");
                    break;
                case INVALID:Log.i("YAZAN", "INVALID");
                    break;
                case SCANNING:Log.i("YAZAN", "SCANNING");
                    break;
                case UNINITIALIZED:Log.i("YAZAN", "UNINITIALIZED");
                    break;
                default:Log.i("YAZAN", "Unknown");
                    break;
    
                }
                int supl_error=intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1);
                if(supl_error==WifiManager.ERROR_AUTHENTICATING){
                    Log.i("YAZAN", "ERROR_AUTHENTICATING!");
                }
            }//if
    
        }// onReceive()
    

    你在哪里找到 wifi.disconnect(); 这就是我打断连接的方式 . 剩下的就是获取网络名称或mac地址以允许或禁止该过程完成

    权限:

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
    

    添加广播接收器:

    <receiver android:name=".MyNetworkMonitor" >
                <intent-filter>
                    <action android:name="android.net.wifi.supplicant.STATE_CHANGE" />
                    <action android:name="android.net.wifi.supplicant.CONNECTION_CHANGE" />
    
                    <action android:name="android.net.wifi.STATE_CHANGE" />
    
                </intent-filter>
            </receiver>
    

    谢谢

相关问题