我们正在构建一款需要访问Web服务的Android游戏 - 所以我们在自己的服务器上运行PHP编写的RESTful API。 API提供的是:创建用户,登录,下载游戏,检索游戏列表,提交分数...... 等等。现在我想,如果有经验的用户获得 URL格式的API - 他/她将能够以多种方式废弃系统:
现在我该如何防止这种滥用?
答案 0 :(得分:32)
我认为你永远无法隐藏应用程序调用的URL (如果我正在运行root-ed安卓手机,我应该可以监视所有网络流量)
但你真正的问题是你需要以某种方式验证你的api。
一种方法是实施OAUTH,但也许这有点过头了。
如果你想要一个简单的机制,那怎么样;
只要秘密保密,没有人可以伪造你的请求。
示例(伪代码):
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
服务器端:
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
答案 1 :(得分:9)
其他人在此处介绍的解决方案称为security through obscurity。基本上他们试图掩盖协议并隐藏实现。这可能会有效,直到有足够能力拆卸应用程序并对协议进行逆向工程。黑客非常有能力做到这一点。
问题是您的应用是否值得破解?像iTunes,DVD或索尼PS3网络这样的计划显然是值得的。如果没有人能够解决问题,那么默默无闻的方法可能会奏效。只是不要欺骗自己,这是不可行的。
由于您无法信任该设备或您的应用,因此您必须信任该用户。为了信任用户,您需要用户识别和授权系统。基本上是您的应用程序的登录。而是滚动你自己的识别系统(登录确认电子邮件等),使用第三方系统:OpenID(谷歌帐户)或OAuth(Facebook,推特)。如果Facebook使用服务器端身份验证方案。
我要做什么:
答案 2 :(得分:3)
你提到用户伪造高分。如果您的用户经过身份验证,这仍可能发生。当游戏上传高分时,您可能希望它也可以上传分数证明。例如,得分为20100,从103个虫子中挤出,飞行1200英里,达到3级,吃掉2个樱桃。这绝不是完美的,但会涵盖低悬的果实。
您应该做的第一件事是拥有经过身份验证的用户。用户ID /密码/会话令牌等,看看你是否能找到一些已经存在的框架。一旦您拥有用户身份验证,请确保您可以使用TLS或类似功能安全地执行此操作。
据我所知,您的服务器无法确定请求是来自您的应用程序(它只是数据包中的位),但您至少可以让某人变得非常恶意。
答案 3 :(得分:1)
如果您确实想要保护连接,那么您将不得不使用公钥加密技术,例如RSA。设备将使用公钥加密登录信息,在服务器端,您必须使用私钥解密。登录后,服务器将发送令牌/加密密钥(响应将是加密的JSON或其他东西),设备将存储该密钥。从那时起,只要会话未到期,设备就会发送使用该令牌加密的所有信息。对于此请求,您不应使用需要更多时间的RSA原因。您可以使用AES256(这是一种流行的私钥加密)与从服务器接收的加密密钥来加密您的请求。
为简单起见,您可以完全放弃RSA(如果您不发送付款信息)并使用带有私钥的AES256执行所有操作。步骤应该是 -
在服务器端
您的请求应带有签名(例如,附加为盐的加密密钥),以便在解密后识别它。如果签名不存在,只需丢弃该请求。
发送回复也是如此。
Android SDK应具有使用AES256和Base 64编码进行加密的方法。
答案 4 :(得分:1)
通过使用通过Google API提供的Oauth令牌,关注Android小组中的these guidelines以保护您的后端。