当前位置:首页 > 行业动态 > 正文

安卓开发之网络验证

网络请求基础

网络权限配置

AndroidManifest.xml 中声明网络权限:

<uses-permission android:name="android.permission.INTERNET" />

常用网络库对比

库名 特点 适用场景
HttpURLConnection Android 内置,轻量级,需手动处理线程和数据解析 简单请求,学习原理
OkHttp 高效、支持缓存/拦截器、自动压缩 复杂网络请求,主流选择
Retrofit 基于 OkHttp,通过注解生成 API 接口,支持 RxJava/Coroutines RESTful API 开发
Volley Google 开源,适合短时间、小数据量请求,内置 ImageLoader 列表加载、图片请求

基础请求示例(OkHttp)

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
        .url("https://api.example.com/login")
        .post(RequestBody.create(JSON, "{"username":"test"}"))
        .build();
client.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        // 处理失败
    }
    @Override
    public void onResponse(Call call, Response response) throws IOException {
        // 处理成功(UI 线程需切换)
    }
});

网络验证流程

验证类型与场景

验证类型 说明 典型场景
Token 验证 服务器返回令牌,后续请求携带该令牌 登录后保持会话
签名验证 客户端签名参数防止改动 敏感操作(如支付)
时间戳验证 请求携带时间戳,服务器校验时效性 防止重放攻击
设备指纹验证 采集设备信息(如 IMEI)生成唯一标识 多设备登录限制

Token 验证流程

  1. 登录获取 Token

    • 客户端发送账号密码 → 服务器验证 → 返回 access_tokenrefresh_token
    • 示例:{"access_token":"abc123","expires_in":3600}
  2. 存储 Token

    安卓开发之网络验证  第1张

    • 推荐使用 SharedPreferences 或 EncryptedSharedPreferences(存储时加密)
    • 避免存入 FileSQLite(易被逆向破解)
  3. 请求携带 Token

    • 在 HTTP Header 中添加 Authorization: Bearer abc123
    • 示例(Retrofit):
      OkHttpClient client = new OkHttpClient.Builder()
          .addInterceptor(chain -> {
              Request request = chain.request()
                  .newBuilder()
                  .addHeader("Authorization", "Bearer " + token)
                  .build();
              return chain.proceed(request);
          })
          .build();
  4. Token 刷新

    • access_token 过期时,用 refresh_token 重新获取
    • 需处理 token 刷新的并发问题(如使用同步锁)

安全优化策略

HTTPS 配置

  • 强制 HTTPS:在 network_security_config.xml 中配置:
    <domain-config cleartextTrafficPermitted="false">
        <domain includeSubdomains="true">api.example.com</domain>
    </domain-config>
  • 证书锁定:将服务器证书的公钥哈希加入配置,防止中间人攻击。

防止抓包与重放攻击

方案 说明
请求签名 使用 HMAC-SHA256 对参数签名,服务器验证签名一致性
时间戳+随机数 请求体包含 timestampnonce,服务器校验时间差(如 5 分钟内)
设备证书绑定 集成设备证书(如 Keystore)生成唯一标识,服务器校验

数据加密示例(AES)

// 加密
SecretKeySpec key = new SecretKeySpec("1234567890abcdef".getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encrypted = cipher.doFinal("sensitive data".getBytes());
// 解密
cipher.init(Cipher.DECRYPT_MODE, key);
String decrypted = new String(cipher.doFinal(encrypted));

常见问题与解决方案

网络请求失败排查表

现象 原因 解决方案
UnknownHostException DNS 解析失败/网络不可用 检查网络权限、域名是否正确
SSLHandshakeException 证书未信任/协议不匹配 配置 HTTPS 证书信任或升级 TLS 版本
SocketTimeoutException 服务器响应慢 设置超时时间(如 connectTimeout=10s)

JSON 解析异常处理

  • 问题:字段缺失或类型不匹配导致 JSONParser 崩溃。
  • 解决方案:使用 GsonTypeToken@SerializedName 注解:
    class User {
        @SerializedName("username") String name; // 对应 JSON 的 "username" 字段
        int age;
    }

相关问题与解答

Q1:如何判断当前网络是否可用?

A1:使用 ConnectivityManager 检测网络状态:

ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
boolean isAvailable = info != null && info.isConnected();

注意:需在 AndroidManifest 中添加 ACCESS_NETWORK_STATE 权限。

Q2:如何防止第三方应用劫持我的网络请求?

A2:通过以下方式增强安全性:

  1. 使用 HTTPS:避免明文传输敏感数据。
  2. 证书绑定:在客户端预埋服务器证书哈希,拒绝未知证书。
  3. 请求签名:对关键接口(如支付)的参数进行 HMAC 签名。
  4. 限制域名:在 network_security_config 中明确允许的
0