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)));

总结

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

相关推荐
雨白5 小时前
Jetpack Compose Navigation 2.x 详解
android·android jetpack
卜锦元5 小时前
音视频媒体服务领域中三种架构方式的定义与区别(Mesh、MCU、SFU)
架构·音视频·媒体
云边云科技5345 小时前
云边云科技SD-WAN解决方案 — 构建安全、高效、智能的云网基石
网络·科技·安全·架构·it·sdwan
414a5 小时前
LingJing(灵境)桌面级靶场平台新增靶机:加密攻防新挑战:encrypt-labs靶场,全面提升安全研究者的实战能力!
安全·渗透测试·lingjing·lingjing(灵境)·网络安全靶场平台
上海云盾-高防顾问6 小时前
智能汽车的“软肋”:车载系统漏洞分析与安全防护框架初探?
安全·车载系统·汽车
q***33376 小时前
数据库高安全—openGauss安全整体架构&安全认证
数据库·安全·架构
roman_日积跬步-终至千里7 小时前
【架构方法论】领域模型:如何通过领域模型,提高系统的可扩展性?
架构
喜欢你,还有大家7 小时前
Kubernetes-架构安装
架构·kubernetes·云计算
jenchoi4137 小时前
【2025-11-12】软件供应链安全日报:最新漏洞预警与投毒预警情报汇总
网络·安全·web安全·网络安全·npm
AcrelZYL7 小时前
古建筑用电安全如何守护,安科瑞ASCB3智能微型断路器
物联网·安全