保护可从Android访问的REST API

Sha*_*iul 31 php security rest android

我们正在构建一款Android游戏,它需要访问Web服务 - 因此我们在PHP中编写了一个RESTful API,它在我们自己的服务器上运行.API提供的是:创建用户,登录,下载游戏,检索游戏列表,提交分数......等等.现在我想,如果一些有经验的用户获得API 的URL格式 - 他/他将能够以多种方式废弃系统:

  • 创建一个脚本并运行它来创建自动用户 - 我想我可以通过CAPTCHA或类似的东西来阻止它.但同样,验证码会惹恼游戏玩家.
  • 恶意用户使用他的浏览器登录,下载游戏然后按照自己的意愿提交分数 - 所有这一切都可以通过简单地从浏览器中输入来调用API.我假设恶意用户以某种方式知道要调用的API URL - 通过在应用程序发出HTTP请求时嗅探.
  • 我需要确保仅从安装游戏的Android设备发出请求.(游戏将免费)

现在我该如何防止这种滥用?

Mat*_*udy 34

我想你永远无法隐藏应用程序调用的URL(如果我运行的是ro​​ot用户手机,我应该可以监视所有网络流量)

但你真正的问题是你需要以某种方式验证你的api.

一种方法是实施OAUTH,但也许这有点过分.

如果你想要一个简单的机制,那么这个怎么样;

  1. 创建一个密钥
  2. 构建api请求(例如https://my.example.com/users/23?fields=name,email)
  3. 哈希此请求路径+加上您的密钥(例如.md5(url + secret_key)=="a3c2fe167")
  4. 将此哈希添加到您的请求中(现在它是https:// .....? fields = name,email&hash = a3c2fe167)
  5. 在api端,执行相同的转换(删除哈希参数)
  6. 检查网址的md5和密钥

只要秘密保密,没有人可以伪造你的要求.

示例(伪代码):

Android方面:

SECRET_KEY = "abc123"

def call_api_with_secret(url, params)
  # create the hash to sign the request
  hash = MD5.hash(SECRET_KEY, url, params)

  # call the api with the added hash
  call_api(url+"&hash=#{hash}", params)
end
Run Code Online (Sandbox Code Playgroud)

服务器端:

SECRET_KEY = "abc123"

def receive_from_api(url, params)
  # retrieve the hash
  url_without_hash, received_hash = retrieve_and_remove_hash(url)

  # check the hash
  expected_hash = MD5.hash(SECRET_KEY, url_without_hash, params)

  if (expected_hash != received_hash)
    raise our exception!
  end

  # now do the usual stuff
end
Run Code Online (Sandbox Code Playgroud)

  • 在Matthew的方法中,秘密密钥永远不会通过网络发送.它是附加到url以创建哈希的"salt".由于散列是单向函数,因此用户无法从中恢复密钥.它需要用户反编译APK并查看源代码以找到密钥.您可以使用代码混淆技术来使这更加困难,但是如果有足够的时间和动力,某人总是可以找到密钥. (9认同)
  • 确实是@JasonLeBrun,我添加了一个伪代码示例.但是,giga,我建议您在PHP中搜索现有框架,而不是创建自己的框架.我相信必须有许多现有的解决方案. (3认同)

Pet*_*ego 9

其他人在这里介绍的解决方案通过默默无闻称为安全性.基本上他们试图掩盖协议并隐藏实现.这可能会有效,直到有足够能力拆卸应用程序并对协议进行逆向工程.黑客非常有能力做到这一点.

问题是你的应用程序是否值得破解?像iTunes,DVD或索尼PS3网络这样的计划显然是值得的.如果没有人能够解决问题,那么默默无闻的方法可能会奏效.只是不要欺骗自己,这是不可行的.

由于您无法信任该设备或您的应用,因此您必须信任该用户.为了信任用户,您需要用户识别和授权系统.基本上是您的应用程序的登录.而是滚动你自己的识别系统(登录确认电子邮件等),使用第三方系统:OpenID(谷歌帐户)或OAuth(Facebook,推特).如果Facebook使用服务器端身份验证方案.

我要做的是:

  1. 允许用户自由玩游戏,直到他们想要在服务器上"保存"结果.
  2. 在保存结果之前,让他们通过上述方法登录.
  3. 使用HTTPS将数据发送到服务器.从受信任的CA购买ssl证书,因此您无需处理自签名证书.