Запретить Android-телефон подключаться к сети WiFi, если мое приложение не одобрит его?

Я хочу разработать приложение, которое может препятствовать подключению к сети WiFi, если я не одобрю его. Я хочу иметь возможность запросить MAC-адрес точки доступа и сравнить его со списком известных адресов, соответствующих SSID. Цель приложения - защитить пользователей от случайного подключения к вредоносным точкам доступа, таким как типы, которые могут быть созданы с помощью ананасных устройств.

Я не понимаю из своего исследования, как я достиг бы этой цели. Вопросы, такие как Как получить уведомление о изменении статуса сети Wi-Fi? объясняют, как обнаружить соединение, но для моего случая использования, который уже слишком поздно.

Ни ConnectivityManager, ни WifiManager, похоже, не предлагают способы добавления слушателей, которые могут прервать соединение.

Некоторые мысли, которые я имел для решения:

  • Установите себя как прокси-сервер и принимайте решение о том, разрешать ли данные. Однако это не похоже на опцию Устанавливаются ли настройки прокси-сервера Android для всех приложений на устройстве? (подсказка: ответ "Нет" ).

  • Замените существующий менеджер WiFi чем-то вроде моего собственного создания. Тем не менее, я действительно пытался найти любую информацию в руководствах разработчика Android относительно замены компонентов системы. Следовательно, я не уверен, что это возможно на ненарушенных телефонах.

  • Сохраните сетевые пароли в моем приложении и установите пароли в диспетчере WiFi на бессмысленные значения. Затем закрепите широковещательное сообщение, которое предупреждает о неудавшемся соединении (предположительно, что-то вроде WifiManager.WPS_AUTH_FAILURE) и выборочно решает снова подключиться к этой сети. Возможно, это возможное (если не уродливое) решение, но могу ли я установить пароль обратно на бессмысленное значение, пока сеть все еще подключена, чтобы мы не могли спокойно подключиться к другому SSID с тем же именем? Я не уверен. Мне кажется, что устройства ананаса, вероятно, будут принимать любой пароль, тем самым делая этот подход недействительным.

  • Найдите способ запретить Android автоматически подключаться к известным сетям (т.е. сети, которые использовались до этого или иметь с ними пароль). Тогда я смогу управлять всеми подключениями/отключением от своего приложения. Однако я не могу понять, как это сделать вручную на моем телефоне, поэтому я сомневаюсь, что это возможно программно.

Может ли кто-нибудь предложить подход, который будет работать на некорневом телефоне?

Ответы

Ответ 1

Вы не можете реализовать очень надежную систему без укорачивания устройства. Здесь, ближе всего вы можете получить, я думаю:

  • Используйте getConfiguredNetworks(), чтобы получить список сетей, настроенных в настоящее время на пользовательском устройстве.
  • Для каждого WifiConfiguration в списке установите общедоступное поле BSSID на нужную "безопасный" MAC-адрес
  • Вызовите saveConfiguration(), чтобы сохранить изменения.

В качестве альтернативы для шага (2.) вы можете вызвать disableNetwork() для каждой настроенной сети и выборочно включить их на основе BSSID. Обратите внимание, что MAC-адреса все еще могут быть легко подделаны.

Ответ 2

вы можете прослушивать изменение соединения Wi-Fi и действовать на этих событиях, чтобы отключить 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));
            }
        }
    }
};

Ответ 3

как вы знаете при подключении к Wi-Fi, приложение sifi manager отображает сообщение подсказки под именем Wifi, которое подключается,

как подключение, аутентификация, получение IP-адреса и т.д.

поэтому я попытался найти, как определить те этапы подключения к сети Wi-Fi я пришел к ответу, показывая, как это делается, это было сделано с помощью приемника до SUPPLICANT_STATE_CHANGED_ACTION

и я попытался реализовать его, добавив код, чтобы просто отключиться... и это было успешным, поскольку Wi-Fi никогда не подключался, значок не появлялся на панели уведомлений и журналы продолжают повторять шаги, хотя некоторые из них говорят о соединении (в журналах), но на самом устройстве ничего не появляется, поэтому, возможно, он подключился к подобным (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>

спасибо