如何让Requests模块通过Flask自建API的身份认证?
Alright, let's tackle this problem step by step. The core issue here is that you're not properly handling session persistence and CSRF token retrieval when using Requests to authenticate against your Flask API. Flask-WTF's CSRF protection and Flask-Login's @login_required both rely on session cookies and valid tokens to work, so let's make sure we're covering all bases.
First, Let's Recap the Key Requirements
Your setup has:
- A login form with
username,password, and hiddencsrf_token(from Flask-WTF) - An
/authenticateendpoint (likely the GET route for the login page) - Protected API routes locked with
@login_required - You can hit
/authenticatebut can't get past authentication to access protected resources
Step-by-Step Solution Code
Here's a working script that handles CSRF token extraction, session persistence, and authentication:
import requests from bs4 import BeautifulSoup # Initialize a session to persist cookies across requests session = requests.Session() # Step 1: Fetch the login page to get a valid CSRF token and initial session cookie AUTH_PAGE_URL = "http://your-api-domain/authenticate" response = session.get(AUTH_PAGE_URL) response.raise_for_status() # Fail fast if the page can't be retrieved # Parse the HTML to extract the CSRF token soup = BeautifulSoup(response.text, "html.parser") csrf_token = soup.find("input", {"name": "csrf_token"})["value"] # Step 2: Send the login POST request with credentials and CSRF token # Note: Replace LOGIN_POST_URL with your actual login processing endpoint (e.g., "/login") LOGIN_POST_URL = "http://your-api-domain/login" login_payload = { "username": "your-username", "password": "your-password", "csrf_token": csrf_token } login_response = session.post(LOGIN_POST_URL, data=login_payload) login_response.raise_for_status() # Verify login success (adjust this check based on your API's response) if "Login successful" in login_response.text or login_response.status_code == 200: print("Authentication succeeded!") else: print(f"Login failed: {login_response.text}") exit(1) # Step 3: Access the protected API endpoint using the authenticated session PROTECTED_API_URL = "http://your-api-domain/your-protected-resource" protected_response = session.get(PROTECTED_API_URL) print("Protected API Response:", protected_response.json()) # Adjust based on your API's output
Critical Things to Check
Use
requests.Session(): This is non-negotiable. It automatically persists cookies (like Flask's session cookie) across requests, which is how Flask-Login tracks authenticated users. If you're making separaterequests.get()/post()calls without a session, each request is a new, unauthenticated session.Correct Login Endpoint: Make sure
LOGIN_POST_URLpoints to the route that processes login submissions (not just the GET/authenticatepage). For example, your Flask code probably has something like:@app.route("/login", methods=["POST"]) def login(): # Handle form validation, call login_user(), etc.If you're posting to
/authenticateinstead of/login, that's likely why authentication isn't working.CSRF Token Extraction: Flask-WTF embeds the CSRF token in the form as a hidden input. Using BeautifulSoup to parse the HTML is reliable, but if your
/authenticateendpoint returns JSON instead of HTML, you can fetch the token from the response JSON (if you've set up your API to expose it that way).Payload Format: Use
data=login_payload(notjson=login_payload) because Flask-WTF expects form-encoded data (not JSON) for form submissions.Flask-Side Authentication Setup: Double-check that your Flask login route is correctly calling
login_user(user)from Flask-Login, which sets the authenticated session cookie.
Troubleshooting Tips
- Print
session.cookiesafter login to confirm thesessioncookie is present. - Check the login response content for error messages (e.g., invalid credentials, missing CSRF token).
- If your API uses HTTPS, make sure Requests isn't having SSL issues (add
verify=Falsetemporarily for testing, but don't use it in production).
内容的提问来源于stack exchange,提问作者ebd




