iT邦幫忙

2024 iThome 鐵人賽

DAY 30
0
自我挑戰組

30 天程式學習筆記:我的自學成長之路系列 第 30

[DAY 30]打造全面的API:身份驗證、Swagger文件、請求次數限制

  • 分享至 

  • xImage
  •  

昨天是簡單的API範例,今天要實現更進階的 API 應用,擴展 API 功能,並使用 Ngrok 將它公開給其他用戶。進階應用包括 API 的多路由、身份驗證,以及與第三方服務的集成。

以下是一個進階的 API 應用示例,結合 Flask 和 Ngrok,並展示如何進行身份驗證、處理不同的 HTTP 請求方法,以及利用 Ngrok 讓外部用戶可以訪問 API。

一、進階 API 應用示例

1. 設定環境

pip install flask ngrok pyngrok

2. 編寫進階的 Flask API

from flask import Flask, jsonify, request, abort
from pyngrok import ngrok

app = Flask(__name__)

# 模擬數據庫
users = {
    "user1": {"name": "Alice", "age": 30},
    "user2": {"name": "Bob", "age": 25}
}

# 身份驗證
def check_auth(token):
    # 假設的 API token 驗證
    return token == "secret-token"

@app.route('/api/users', methods=['GET'])
def get_users():
    token = request.headers.get('Authorization')
    if not check_auth(token):
        return abort(401)  # Unauthorized
    return jsonify(users)

# 查詢特定用戶資料
@app.route('/api/users/<username>', methods=['GET'])
def get_user(username):
    token = request.headers.get('Authorization')
    if not check_auth(token):
        return abort(401)

    user = users.get(username)
    if user:
        return jsonify(user)
    else:
        return abort(404)  # Not Found

# 新增用戶資料
@app.route('/api/users', methods=['POST'])
def add_user():
    token = request.headers.get('Authorization')
    if not check_auth(token):
        return abort(401)

    if not request.json or not 'name' in request.json:
        return abort(400)  # Bad Request

    new_user = {
        "name": request.json["name"],
        "age": request.json.get("age", 0)
    }
    user_id = f"user{len(users) + 1}"
    users[user_id] = new_user
    return jsonify({user_id: new_user}), 201  # Created

# 啟動 ngrok 並公開 API
if __name__ == "__main__":
    # 啟動 Ngrok 隧道
    public_url = ngrok.connect(5000)
    print(" * Public URL:", public_url)

    # 運行 Flask 應用
    app.run(port=5000)

3. 說明

  1. 身份驗證: API 檢查 Authorization 標頭中的 token,如果不匹配將返回 401 Unauthorized 狀態碼。
  2. 多路由處理:
    • /api/users 支持 GETPOST 方法。
    • /api/users/<username> 支持 GET 方法,來查詢特定用戶資料。
  3. 錯誤處理: API 會返回 400 Bad Request404 Not Found 錯誤,來處理無效的請求。

4. 啟動 API

運行這個 Python 應用後,你會在終端中看到此輸出:

* Public URL: http://xxxxxxxx.ngrok-free.app

此時,Ngrok 已經為你的本地 API 創建了一個公開的 URL。你可以將這個 URL 發送給外部用戶,讓他們訪問 API。

5. 測試 API

你可以使用 Postmancurl來進行測試:

5.1 使用 Postman 發送請求

如果你正在使用 Postman 來測試這個 API,設置如下:

  1. 選擇 HTTP 方法(例如 GETPOST)。
  2. 輸入 URL,例如:http://xxxxxxxx.ngrok-free.app/api/users
  3. 添加 Headers
    • 點擊 "Headers" 標籤。
    • 在 Key 欄輸入 Authorization
    • 在 Value 欄輸入 secret-token
  4. 發送請求

5.2 使用 curl 發送請求

在這個請求中,Authorization 標頭包含了 secret-token,這樣伺服器端的 Flask 應用就能識別這個請求來自於管理員,並根據管理員的角色授予相應的權限。

curl -H "Authorization: secret-token" http://xxxxxxxx.ngrok-free.app/api/users

二、進階功能擴展

1. 角色和權限管理

基於角色的權限控制,讓不同的用戶具有不同的 API 使用權限,例如:

def check_auth(token, required_role=None):
    # 根據 token 驗證用戶角色
    if token == "admin-token":
        return required_role in ["admin", "user"]
    elif token == "user-token":
        return required_role == "user"
    return False

2. API 文檔

使用 Flask-RESTfulflasgger 生成 Swagger 文檔,讓使用者可以通過網頁介面直接查看和測試 API。

安裝必要套件:

pip install flask-restful flasgger

集成 Flask-RESTfulflasgger

from flask import Flask
from flask_restful import Api, Resource
from flasgger import Swagger

app = Flask(__name__)
api = Api(app)
swagger = Swagger(app)

class HelloWorld(Resource):
    def get(self):
        """
        This is an example endpoint.
        ---
        responses:
          200:
            description: A successful response
        """
        return {'hello': 'world'}

api.add_resource(HelloWorld, '/')

if __name__ == '__main__':
    app.run(debug=True)

訪問 Swagger 文檔:

在啟動 Flask 應用後,你可以在瀏覽器中打開 http://127.0.0.1:5000/apidocs 來查看 Swagger 自動生成的 API 文檔。這將顯示所有已定義的 API 路徑以及它們的描述,讓你可以測試不同的 API 調用。

3. 提高安全性 - 使用 OAuth 2.0 進行安全認證

你可以使用 Authlib 來集成 OAuth 2.0,為你的 API 提供更高的安全性。

3.1 安裝 Authlib

pip install authlib

3.2 OAuth 2.0 實作範例

from authlib.integrations.flask_oauth2 import AuthorizationServer, ResourceProtector
from authlib.oauth2.rfc6749 import grants
from flask import Flask

app = Flask(__name__)

# 假設你已經有一個 Authorization Server 設定
server = AuthorizationServer(app)

@app.route('/api/protected')
def protected():
    # 需要 OAuth 認證
    return {'message': 'This is a protected route'}

if __name__ == '__main__':
    app.run(debug=True)

https://ithelp.ithome.com.tw/upload/images/20240920/20167760oiRXMomPmt.png

4. 增加 API 請求速率限制

為了防止 API 被濫用,你可以使用 Flask-Limiter 來限制每個 IP 的請求次數。

安裝 Flask-Limiter

pip install Flask-Limiter

集成 Flask-Limiter

from flask import Flask
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

app = Flask(__name__)
limiter = Limiter(app, key_func=get_remote_address)

@app.route('/api')
@limiter.limit("5 per minute")
def index():
    return 'This route is limited to 5 requests per minute'

if __name__ == '__main__':
    app.run(debug=True)

https://ithelp.ithome.com.tw/upload/images/20240920/20167760WFuYHUYhdI.png

這樣可以限制每個 IP 每分鐘只能訪問 5 次,防止濫用。


上一篇
[DAY 29]Python API 教學:使用 Flask 和 ngrok 打造你的公開服務
系列文
30 天程式學習筆記:我的自學成長之路30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言