You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Flask编写的Rest API仅对Android应用注册页开放?

关于Flask做Android后端API及接口安全的解决方案

先明确:Python Flask完全适合为Android应用开发Rest API

Flask轻量灵活,开发成本低、部署简单,很多中小型移动端项目的后端都是用Flask搭建的,完全能满足Android应用的API需求,不用有顾虑。

解决POST接口被任意访问的安全方案

针对你的问题,下面是几种实用的方案,能让接口只对你的Android应用开放:

1. 嵌入API密钥验证

在你的Android应用中嵌入一个唯一的API密钥,每次请求POST接口时,在请求头里带上这个密钥,Flask后端验证密钥的合法性:

  • Android端请求时,添加请求头X-API-Key: 你的唯一密钥
  • Flask端修改代码验证:
from flask import request, jsonify

# 预设的API密钥,要和Android端一致,建议通过环境变量读取,不要硬编码在公开代码里
VALID_API_KEY = "your_unique_secret_key_here"

@app.route('/user/', methods=['GET','POST'])
def user_page():
    if request.method == 'GET':
        id_parameter = request.args.get('id')
        if not id_parameter:
            return jsonify({'Error':'Invalid parameter(s)'})
        user = getUserById(id_parameter)
        if not user:
            return jsonify({'Error':'Invalid parameter(s)'})
        return jsonify({
            'UserID':user.id,
            'Username':user.username
            # 注意!这里绝对不能返回明文密码,这是严重的安全漏洞!
        })
    elif request.method == 'POST':
        # 先验证API密钥
        api_key = request.headers.get('X-API-Key')
        if api_key != VALID_API_KEY:
            return jsonify({'Error':'Unauthorized'}), 401
        
        # 建议POST用request.get_json()或request.form获取参数,而非request.args(GET参数用args)
        username = request.get_json().get('username')
        password = request.get_json().get('password')
        # 若用表单提交则改为:username = request.form.get('username')
        
        if not username or not password:
            return jsonify({'Error':'Missing parameters'}), 400
        
        insertUsers(username, password)
        return jsonify({'Status':'SUCCESS'}), 201

注意:API密钥不要直接硬编码在Android应用代码里,可以通过代码混淆、本地加密或者后端动态下发的方式处理,防止被反编译提取。

2. 请求签名验证(更安全)

比单纯的API密钥更安全,能防止密钥被抓包后滥用。核心逻辑是:

  • Android端将请求参数、当前时间戳用约定的密钥生成签名
  • 把时间戳和签名一起放在请求头里发送
  • Flask端按相同规则生成签名,对比是否一致,同时验证时间戳是否在有效范围内(防止重放攻击)

示例代码:

import hmac
import hashlib
from datetime import datetime

SECRET_KEY = "your_shared_secret"
ALLOWED_TIME_DIFF = 300  # 允许的时间差(秒),比如5分钟

def verify_signature(timestamp, signature, data):
    # 生成待签名字符串:时间戳+原始请求数据
    sign_string = f"{timestamp}{data}"
    # 用HMAC-SHA256生成签名
    expected_sign = hmac.new(SECRET_KEY.encode(), sign_string.encode(), hashlib.sha256).hexdigest()
    # 验证签名+时间戳有效性
    now = datetime.now().timestamp()
    if abs(now - float(timestamp)) > ALLOWED_TIME_DIFF:
        return False
    return hmac.compare_digest(expected_sign, signature)

@app.route('/user/', methods=['POST'])
def user_page():
    timestamp = request.headers.get('X-Timestamp')
    signature = request.headers.get('X-Signature')
    data = request.get_data(as_text=True)  # 获取原始请求数据
    
    if not timestamp or not signature or not verify_signature(timestamp, signature, data):
        return jsonify({'Error':'Unauthorized'}), 401
    
    # 后续参数处理及插入逻辑...

Android端需要实现对应的签名生成逻辑,确保和后端规则完全一致。

3. 辅助手段:验证User-Agent(仅作为补充)

可以在请求头里设置自定义的User-Agent,后端验证是否匹配,但这个容易伪造,只能作为辅助安全措施:

VALID_USER_AGENT = "YourAndroidApp/1.0.0"

if request.headers.get('User-Agent') != VALID_USER_AGENT:
    return jsonify({'Error':'Unauthorized'}), 401

内容的提问来源于stack exchange,提问作者asodisc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 12:54:53