如何验证移动钱包小游戏向服务器发起的请求来自正版应用?
Hey there, let’s dig into how you can make sure your server only accepts requests from your official mobile wallet app—super important for that in-game feature you’re running, especially since you’re using a traditional web service setup.
Here are actionable, layered strategies tailored to your stack:
1. Server-Side App Signature Verification
Every official Android/iOS app has a unique digital signature that can’t be replicated without your original signing keys. This is one of the most reliable checks:
- For Android: Have your app pull its signature via the
PackageInfoclass, hash it with SHA-256, and send the hash in a custom request header (e.g.,X-App-Signature). On your server, store the SHA-256 hash of your official app’s signature, and reject any request where the sent hash doesn’t match. - For iOS: Use Apple’s App Attestation service to let Apple confirm the app’s authenticity, then pass that attestation result to your server. Alternatively, validate the app’s unique bundle ID (only you can publish apps with your bundle ID) paired with an obfuscated secret in the app.
Pro tip: Always send this hash over HTTPS to prevent interception.
2. Short-Lived, Session-Bound Tokens
Static API keys are easy to reverse-engineer—swap them for dynamic, tied tokens:
- When the user opens your app, send an obfuscated device fingerprint (a hashed combo of Android ID/IDFA + app version) to your server. The server generates a unique token tied to that fingerprint, sets an expiration (e.g., 1 hour), and sends it back.
- Every subsequent request must include this token. Your server checks if the token is active, unexpired, and matches the initial fingerprint.
Add-on: Include a timestamp in each request, and reject any request where the timestamp is more than 5 minutes old. This blocks replay attacks.
3. Request Payload Signing
Boost token security by signing the entire request payload:
- Hide a private key in your app (use obfuscation tools like ProGuard for Android or Xcode’s obfuscation to split the key into pieces and scatter it in your code—never store it plaintext!).
- For every request, have the app sign the full payload (token, timestamp, game data, etc.) with this private key, and send the signature along with the request.
- Your server uses the matching public key to verify the signature. If it doesn’t align, reject the request immediately.
4. Defensive Device/Environment Checks
Add layers to catch suspicious setups:
- On the app side, check if it’s running in an emulator, on a rooted/jailbroken device, or if debug tools are attached. If any of these are true, either block request sending or send a flag to your server for extra scrutiny.
- On the server side, cross-reference device info (model, OS version) with your user base’s typical data. Flag requests from never-seen-before device models or outdated OS versions for manual review.
5. Context-Aware Rate Limiting
Even with all the above, rate limiting is a non-negotiable safety net:
- Set general limits (e.g., 100 requests per minute per token/device).
- For game-specific actions (like spins or moves), limit to what a human could reasonably do—maybe 10 actions per minute.
- Temporarily block devices/tokens that exceed limits (e.g., 15 minutes) or require additional verification.
A Quick Reality Check
No single method is 100% unbreakable—attackers love reverse-engineering apps. But combining 2-3 of these layers (like signature checks + payload signing + rate limiting) makes it exponentially harder for them to fake requests successfully. Start with signature and token methods first, as they’re the most impactful for your traditional web service setup.
内容的提问来源于stack exchange,提问作者Danh Thanh Nguyen

