android - 如何检查不受限制的 Internet 访问? (强制门户检测)

标签 android http authentication redirect connectivity

我需要可靠地检测设备是否具有完整的互联网访问权限,即用户不限于强制门户(也称为围墙花园),即有限的子网,它强制用户在表单上提交他们的凭据以获得完全访问权限。

我的应用程序正在自动执行身份验证过程,因此在开始登录 Activity 之前了解无法完全访问互联网非常重要。

问题不是关于如何检查网络接口(interface)是否已启动并处于连接状态。这是为了确保设备具有不受限制的互联网访问权限,而不是沙盒内网段。

到目前为止我尝试过的所有方法都失败了,因为连接到任何知名主机都不会引发异常,而是返回有效的 HTTP 200 响应代码,因为所有请求都被路由到登录页面。

这是我尝试过的所有方法,但由于上述原因,它们都返回 true 而不是 false:

1:

InetAddress.getByName(host).isReachable(TIMEOUT_IN_MILLISECONDS);
isConnected = true; <exception not thrown>

2:

Socket socket = new Socket();
SocketAddress sockaddr = new InetSocketAddress(InetAddress.getByName(host), 80);
socket.connect(sockaddr, pingTimeout);
isConnected = socket.isConnected();

3:

URL url = new URL(hostUrl));
URLConnection urlConn = url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection) urlConn;
httpConn.setAllowUserInteraction(false);
httpConn.setRequestMethod("GET");
httpConn.connect();
responseCode = httpConn.getResponseCode();
isConnected = responseCode == HttpURLConnection.HTTP_OK;

那么,如何确保我连接到实际主机而不是登录重定向页面?显然,我可以从我使用的“ping”主机检查实际响应正文,但它看起来不是一个合适的解决方案。

最佳答案

作为引用,这里是来自 Android 4.0.1 AOSP 代码库的“官方”方法: WifiWatchdogStateMachine.isWalledGardenConnection() .我将下面的代码包括在内,以防万一将来链接断开。

private static final String mWalledGardenUrl = "http://clients3.google.com/generate_204";
private static final int WALLED_GARDEN_SOCKET_TIMEOUT_MS = 10000;

private boolean isWalledGardenConnection() {
    HttpURLConnection urlConnection = null;
    try {
        URL url = new URL(mWalledGardenUrl); // "http://clients3.google.com/generate_204"
        urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.setInstanceFollowRedirects(false);
        urlConnection.setConnectTimeout(WALLED_GARDEN_SOCKET_TIMEOUT_MS);
        urlConnection.setReadTimeout(WALLED_GARDEN_SOCKET_TIMEOUT_MS);
        urlConnection.setUseCaches(false);
        urlConnection.getInputStream();
        // We got a valid response, but not from the real google
        return urlConnection.getResponseCode() != 204;
    } catch (IOException e) {
        if (DBG) {
            log("Walled garden check - probably not a portal: exception "
                    + e);
        }
        return false;
    } finally {
        if (urlConnection != null) {
            urlConnection.disconnect();
        }
    }
}

这种方法依赖于一个特定的 URL,mWalledGardenUrl = "http://clients3.google.com/generate_204" 总是返回一个 204 响应代码。即使 DNS 受到干扰,这也会起作用,因为在这种情况下,将返回 200 代码而不是预期的 204。我看到一些强制门户网站欺骗了对这个特定 URL 的请求,以防止在 Android 设备上显示 Internet 无法访问 消息。

Google 有这个主题的变体:获取 http://www.google.com/blank.html 将返回一个具有零长度响应的 200 代码 body 。所以如果你得到一个非空的 body ,这将是另一种判断你在围墙花园后面的方法。

Apple 有自己的 URL 来检测强制门户:当网络启动时,IOS 和 MacOS 设备将连接到像 http://www.apple.com/library/test/success.html 这样的 URL , http://attwifi.apple.com/library/test/success.html , 或 http://captive.apple.com/hotspot-detect.html它必须返回 200 的 HTTP 状态代码和包含 Success 的正文。

NOTE: This approach will not work in areas with regionally restricted Internet access such as China where the whole country is a walled garden, and where some Google/Apple services might be blocked. Some of these might not be blocked: http://www.google.cn/generate_204, http://g.cn/generate_204, http://gstatic.com/generate_204 or http://connectivitycheck.gstatic.com/generate_204 — yet these all belong to google so not guaranteed to work.

关于android - 如何检查不受限制的 Internet 访问? (强制门户检测),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13958614/

相关文章:

android - 如何在 Android 中自定义权限对话框?

unit-testing - 如何使用Ginkgo对HTTP请求进行单元测试?

php - 用户身份验证 PHP mySQL 不工作

Android 4.0 PhoneGap 问题

Android 字符集问题下载 utf-8 网页

android - CustomList 未添加到 fragment 中

java - 如何捕获本地 HTTP 流量

http - 是否可以在沙盒中使用 Instagram tags/xxx/media/recent 端点?

php - Laravel AJAX 请求发布错误代码 : 419 after session id changed when logging in using laravel auth

authentication - 前端用户认证和后端用户认证的区别