Android Wifi认证(Portal)代码解析DNS并使用Socket发送Http请求完成认证

最近在一能开启多网络上网的Android系统中遇到连接认证WIFI问题,通过http://connectivitycheck.gstatic.com/generate_204不能完成认证。

可能原因为以下几种:

1、在wifi和移动网络同时开启的情况下,网络通过移动网络请求,返回的结果为204,不需要认证;

2、使用bindProcessToNetwork绑定wifi网络发送请求,网络请求结果为DNS解析失败(该定制Android平台特有);

为了解决这个问题,决定自己解析DNS并使用Socket发送Http

DNS解析关键代码:

ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
byteBuffer.put(dnsHead);
String[] strs = domin.split("\\.");
for (String s : strs) {
    byteBuffer.put((byte) s.length());
    byteBuffer.put(s.getBytes());
}
byteBuffer.put((byte) 0);
byteBuffer.put(queries_end);
byteBuffer.flip();
int len = byteBuffer.limit() - byteBuffer.position();
byte[] sendData = new byte[len];
byteBuffer.get(sendData);
FlyLog.d("send:%s", ByteTools.bytes2HexString(sendData));

DatagramSocket socket = new DatagramSocket();
socket.setSoTimeout(5000);
DatagramPacket sendpack = new DatagramPacket(sendData, sendData.length, InetAddress.getByName(dns), 53);
socket.send(sendpack);

final byte[] recvBuffer = new byte[1024];
DatagramPacket recvpack = new DatagramPacket(recvBuffer, recvBuffer.length);
socket.receive(recvpack);
byte[] recvData = recvpack.getData();
FlyLog.d(recvpack.getAddress().getHostAddress() + ":" + recvpack.getPort() + "--len" + recvpack.getData().length);
FlyLog.d("recv:%s", ByteTools.bytes2HexString(recvData, 64));
int answer = ByteTools.bytes2Short2(recvData, 4);
if (answer > 0) {
    ByteBuffer answerBuffer = ByteBuffer.wrap(recvData);
    answerBuffer.position(len);
    for (; ; ) {
        short name = answerBuffer.getShort();
        if (name == 0) break;
        short type = answerBuffer.getShort();
        short _cls = answerBuffer.getShort();
        int ttl = answerBuffer.getInt();
        short length = answerBuffer.getShort();
        byte[] content = new byte[length];
        answerBuffer.get(content);
        if (type == 1) {
            String ip = (content[0] & 0xff) + "." + (content[1] & 0xff) + "." + (content[2] & 0xff) + "." + (content[3] & 0xff);
            FlyLog.d("get ip address=%s", ip);
            return ipCheck(ip) ? ip : null;
        }
    }
}

Socket发送HTTP请求关键代码:

SocketAddress socketAddress = new InetSocketAddress(ip, 80);
socket = new Socket();
socket.setSoTimeout(5000);
socket.connect(socketAddress);

FlyLog.d("localAddress:"+socket.getLocalAddress());

OutputStreamWriter streamWriter = new OutputStreamWriter(socket.getOutputStream());
bufferedWriter = new BufferedWriter(streamWriter);
bufferedWriter.write("GET /generate_204 HTTP/1.1\r\n");
bufferedWriter.write("Host: " + host + "\r\n");
bufferedWriter.write("\r\n");
bufferedWriter.flush();
BufferedInputStream streamReader = new BufferedInputStream(socket.getInputStream());
bufferedReader = new BufferedReader(new InputStreamReader(streamReader, StandardCharsets.UTF_8));
String statusLine = bufferedReader.readLine();
if (TextUtils.isEmpty(statusLine)) {
    FlyLog.d("Http result empty");
    return 204;
} else {
    FlyLog.d(statusLine);
    if (statusLine.startsWith("HTTP/1.")) {
        int codePos = statusLine.indexOf(' ');
        if (codePos > 0) {
            int phrasePos = statusLine.indexOf(' ', codePos + 1);
            if (phrasePos < 0)
                phrasePos = statusLine.length();
            try {
                return Integer.parseInt(statusLine.substring(codePos + 1, phrasePos));
            } catch (NumberFormatException e) {
                return 204;
            }
        }
    }
}
bufferedReader.close();
bufferedWriter.close();
socket.close();

进程绑定Wifi网络代码:

Network defaultNetwork = cm.getActiveNetwork();
FlyLog.d("Active Network:" + defaultNetwork);
Network[] networks = cm.getAllNetworks();
for (Network network : networks) {
    NetworkInfo netInfo = cm.getNetworkInfo(network);
    if (netInfo != null && (netInfo.getType() == ConnectivityManager.TYPE_WIFI)) {
        if(!network.equals(defaultNetwork)){
            setNetwork = cm.bindProcessToNetwork(network);
            FlyLog.d("Bind Network:" + network);
            FlyLog.d("Active Network:" + cm.getActiveNetwork());
            break;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值