如何打造不可被利用的Python登录系统?服务端安全改造技术咨询
Hey there! Let's walk through how to secure your Python login system—you don't need PHP to fix this, we can harden the Python + MySQL setup directly. Let's start with the critical flaws in your current code, then fix them step by step:
1. 永远不要存储明文密码
This is the most dangerous issue right now: if your database is ever accessed by an attacker, all user passwords will be exposed immediately. You need to store hashed passwords (using a secure algorithm like bcrypt) instead of plain text.
改进方案:
- When creating user accounts, hash the password first before saving it to the database
- When logging in, hash the user's input and compare it to the stored hash (never compare plain text)
Example code (first install bcrypt with pip install bcrypt):
import bcrypt import mysql.connector # Connect to DB (we'll fix credentials later) conn = mysql.connector.connect(host="localhost", user="pazearn_user", password="secure_db_pass", database="pazearn") cursor = conn.cursor() # --- User Registration Example (run once per new user) --- def register_user(username, password): # Hash the password hashed_pw = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()) # Store hash, not plain text insert_query = "INSERT INTO accounts (username, password_hash, money) VALUES (%s, %s, %s)" cursor.execute(insert_query, (username, hashed_pw, 0)) conn.commit() # --- Login Logic --- print("Welcome to Pazearn\nLogin to your account\n") username_input = input("Username: ") password_input = input("Password: ") # Only fetch the relevant user's data (not all accounts!) select_query = "SELECT password_hash, money FROM accounts WHERE username = %s" cursor.execute(select_query, (username_input,)) result = cursor.fetchone() isval = False money = 0 if result: stored_hash = result[0] # Verify the hashed password if bcrypt.checkpw(password_input.encode('utf-8'), stored_hash.encode('utf-8')): isval = True money = result[1] if not isval: print("[SYSTEM]: Invalid username or password, restart to try again.") time.sleep(10) quit() else: os.system("cls") print(f"[SYSTEM]: Welcome back, {username_input}") print("[SYSTEM]: Booting system, please wait.") time.sleep(2)
2. Use Parameterized Queries to Avoid SQL Injection
Your current code pulls all accounts into the local script to check credentials—this is inefficient and risky. If you ever modify the query to use dynamic input (like directly inserting the username into the SQL string), attackers could use SQL injection to steal data or take over your database.
Parameterized queries (using %s as placeholders and passing values as a tuple to execute()) eliminate this risk, as shown in the login example above.
3. Stop Hardcoding Database Credentials
Putting your MySQL username and password directly in the code is a huge risk—if your code is shared or leaked, anyone can access your database.
改进方案:
- Store credentials in environment variables
- Or use a dedicated config file (e.g.,
config.ini) and make sure it's never committed to version control
Example with environment variables:
import os import mysql.connector # Pull credentials from environment variables db_host = os.getenv("DB_HOST", "localhost") db_user = os.getenv("DB_USER") db_pass = os.getenv("DB_PASSWORD") db_name = os.getenv("DB_NAME", "pazearn") conn = mysql.connector.connect( host=db_host, user=db_user, password=db_pass, database=db_name )
4. Follow the Principle of Least Privilege
Your current code uses the root MySQL user, which has full access to every database on your server. If this credential is compromised, an attacker can delete or modify all your data.
改进方案:
Create a dedicated MySQL user with only the permissions it needs:
-- Run this in MySQL to create a restricted user CREATE USER 'pazearn_user'@'localhost' IDENTIFIED BY 'your_secure_password'; GRANT SELECT, INSERT, UPDATE ON pazearn.accounts TO 'pazearn_user'@'localhost'; FLUSH PRIVILEGES;
Then use this user instead of root in your Python code.
5. Add Extra Security Layers
- Limit Login Attempts: Lock an account for 15 minutes after 3 failed login attempts to prevent brute-force attacks
- Session Management: If this system needs persistent logins, generate a random session ID (using
uuid), store it in the database with an expiry time, and save it locally on the client instead of relying on plain text credentials - Encrypt Traffic: If this is a network-based system (e.g., a web app or API), use HTTPS to encrypt all data between client and server
内容的提问来源于stack exchange,提问作者Zelqify

