Android对于请求数据安全的一些思考

我们Android端的数据请求很容易,通常都是使用Retrofit来实现的。

kotlin 复制代码
/**
 * 申请添加对方为好友。
 *
 * @param from 好友请求发起的用户id
 * @param to 被发起好友请求的用户id
 * @return 好友请求是否送达
 */
@POST("v2/friendRequestSend")
@FormUrlEncoded
suspend fun addFriendRequest(
    @Field("from") from: String,
    @Field("to") to: String
): Flow<ApiResult<Boolean>>

这是使用form表单请求的一种方式。这种请求很容易被伪造,从而绕开客户端做一些盗版的app。那么问题来了,怎么优化?

kotlin 复制代码
@POST("v3/friendRequestSend")
suspend fun addFriendRequestV3(@Body body: RequestBody): Flow<ApiResult<Boolean>>

在请求数据model类的基类中添加一个转换为RequestBody的方法。

kotlin 复制代码
fun toRequestBody() : RequestBody {
    return Gson().toJson(this).toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())
}

先修改为RequestBody的请求方式,然后我们再对RequestBody做文章。

如何防止伪造数据

我们发出去的RequestBody是有一定玄机的,除了业务相关的字段,还应该添加一些公共字段。这些公共字段包括timestamp、random和signature等。先说签名,签名是针对对大部分字段对。将这些字段放入一个按key的字母排序的hashmap,先转为json字符串,再对json字符串做一些加密。这样服务端也对这些字段排序,并按同样的方式进行签名,然后比对客户端传入的数据有没有被修改。如果没有被黑客改过,很好,我们再接着做下一步校验。random是否是按照我们的特定算法随机出来的随机数,并非完全随机。如果不是,则说明不是由客户端签名出来的,直接拒绝请求。说到这里,有些人可能会动脑筋,我抓包,直接按你的数据发送请求不就好了?对不起,平台就是可以为所欲为的。你的签名过期了,我不认!你能把我怎么着?这时timestamp就派上用场了,当然这个还要考虑时区。如果我服务端收到请求的时间减去客户端签名时的时间戳,发现竟然过了整整3秒钟。这时服务端则认为,你是不是穿越过来的?都什么年代了,网速竟然可以如此之慢!

如何防止请求数据泄露

如果你的app对请求的安全级别更高,那么你就要使用RSA非对称加密了。生成一个RSA密钥对,即公钥和私钥。这些业务相关的字段就不要传了,先将其转换为json字符串,然后使用RSA的公钥对其进行加密,再传给服务端。服务端使用相对应的私钥对数据进行解密。注意私钥请妥善保管,不要泄露。

###服务端的大致实现

java 复制代码
Req req = new Req("1", "3", "2");
List<String> list = new ArrayList<>();
// 签名数据后面加进去
list.add("signature");
// 创建一个HashMap并添加一些键值对
Map<String, Object> hashMap = new HashMap<>();
Field[] fields = req.getClass().getDeclaredFields();
for (Field field : fields) {
    field.setAccessible(true);
    if (list.contains(field.getName())) {
        continue;
    }
    try {
        hashMap.put(field.getName(), field.get(req));
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

// 将HashMap的键按字母顺序排序
List<String> sortedKeys = new ArrayList<>(hashMap.keySet());
Collections.sort(sortedKeys);

// 创建一个新的按键排序的HashMap
SortedMap<String, Object> sortedMap = new TreeMap(hashMap);

// 将排序后的HashMap转为JSON字符串
// 创建ObjectMapper对象
ObjectMapper objectMapper = new ObjectMapper();

// Jackson生成Java对象为JSON字符串
String jsonString = null;
try {
    jsonString = objectMapper.writeValueAsString(sortedMap);
} catch (JsonProcessingException e) {
    e.printStackTrace();
}
// 解析JSON转为对象
sortedMap.put("signature", encryptToMD5(encryptToAES(jsonString)));

// 签名数据
System.out.println("signature="+encryptToMD5(encryptToAES(jsonString)));

总结

数据安全攻防是一个持续对抗的问题。树大招风,树欲静而风不止。你的平台如果要做大做强,必然要将数据安全放在非常重要的位置,可以说是一个企业的命脉。对数据多做几层加密,养兵千日,用兵一时。一旦有人发出攻击,哪怕复杂度再高一点点,那就对你没有办法。最后祝大家,技术更上一层楼,多多学习新技术,技术的更新换代很快,如果不思进取,则可能在时代的潮流中被淘汰。

相关推荐
johnsong8 小时前
AI前沿日报 · 2026-10-31 | 安全失守——当AI工具被下毒、当云端门户洞开
人工智能·安全
微订校园外卖系统9 小时前
校园外卖多站点管理能做吗?三层权限与对账架构
架构·外卖系统·本地生活·微订
飞飞传输9 小时前
飞驰云联文件交换建设方法论:从单点传输到持续治理
大数据·运维·安全
得帆低代码PaaS9 小时前
企业级 Agent 架构:MCP、Integration、数据与治理能力
大数据·人工智能·架构·ai agent·企业数字化·mcp
孟健12 小时前
实测 agent-desktop:AI 控制桌面不截图、不占鼠标键盘,连点 55 次计算器 0 失误
人工智能·架构·开源
你三大爷14 小时前
Netty / Kafka / Redis 保序问题的源码对比与 NIO 框架主流解法
后端·架构
神鹰手哥_起飞版14 小时前
从一张像素网格,理解康威生命游戏的核心机制
架构
QXWZ_IA15 小时前
高楼遮挡RTK失锁:三层安全网怎么搭
人工智能·安全
衡石科技15 小时前
让多轮分析沿用正确口径:衡石 Data Agent 的上下文工程
安全·chatbi·上下文工程·data agent