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

总结

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

相关推荐
Solar202537 分钟前
机械制造业TOB企业获客软件选型指南:从挑战到解决方案的深度解析
java·大数据·服务器·架构·云计算
MobotStone1 小时前
2026年风口项目:AI漫剧怎么做?这套“傻瓜式”教程请收好
架构
佛系打工仔1 小时前
绘制K线第三章:拖拽功能实现
android·前端·ios
消失的旧时光-19431 小时前
BLoC vs Riverpod:命令式系统 与 声明式系统的两条架构路线
flutter·架构
小当家.1051 小时前
从零构建项目认知:如何画出一张合格的系统架构图(以供应链系统为例)
java·spring boot·学习·架构·系统架构·供应链·实习
我命由我123451 小时前
Android 项目路径包含非 ASCII 字符问题:Your project path contains non-ASCII characters
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
乾元1 小时前
10 个可复制的企业级项目:从需求到交付的 AI 网络工程模板(深度实战版)
运维·网络·人工智能·网络协议·安全
沛沛老爹1 小时前
Web开发者突围AI战场:Agent Skills元工具性能优化实战指南——像优化Spring Boot一样提升AI吞吐量
java·开发语言·人工智能·spring boot·性能优化·架构·企业开发
小范馆2 小时前
解决 Windows 11 安装时提示 “不支持 TPM 2.0” 和 “不支持安全启动” 的问题
windows·安全
wszy18092 小时前
rn_for_openharmony_空状态与加载状态:别让用户对着白屏发呆
android·javascript·react native·react.js·harmonyos