如何在Docker/Kubernetes部署场景下向Flask应用传递用户登录密码
实现方案说明
核心疑问解答
- 用户名密码传递:既可以用HTML原生表单自动生成POST请求,也可以用JS手动发送,不需要依赖jQuery
- POST请求确实需要指向后端专门的登录处理接口,比如我们可以定义
/login作为接收地址 - 不要在前端做密码哈希:只要你用HTTPS对外提供服务(K8s Ingress配置HTTPS证书即可),直接传输明文密码到后端是安全的,前端哈希反而会导致重放攻击风险,正确做法是后端存储哈希后的密码,收到前端传的明文密码后算哈希和存储的值比对
最简实现方案(不需要flask-httpauth)
我们用Flask自带的session功能就能实现,需要先安装依赖pip install flask werkzeug,werkzeug自带密码哈希工具。
修改后的Flask代码
#!flask/bin/python from flask import Flask, render_template, request, redirect, url_for, session from werkzeug.security import generate_password_hash, check_password_hash app = Flask(__name__) # 必须设置secret_key用来加密session,生产环境不要写死在代码里,用环境变量读取 app.secret_key = 'your_secure_secret_key_here_change_in_production' # 模拟存储用户数据,生产环境换成数据库 # 密码是用generate_password_hash('test123')生成的哈希值,示例明文密码是test123 users = { "user@example.com": generate_password_hash("test123") } @app.route('/') def home(): # 已经登录就渲染商品页,没登录就渲染登录页 if 'email' in session: return render_template('products.html') return render_template('login.html') @app.route('/login', methods=['POST']) def login(): email = request.form.get('email') password = request.form.get('password') # 校验用户存在且密码正确 if email in users and check_password_hash(users[email], password): session['email'] = email return redirect(url_for('home')) # 校验失败返回登录页加错误提示 return render_template('login.html', error="邮箱或密码错误") @app.route('/logout') def logout(): session.pop('email', None) return redirect(url_for('home')) @app.errorhandler(400) def bad_request(error): return '<!DOCTYPE html><html><body><div style="text-align: center;">Bad request</div></body></html>' @app.errorhandler(404) def not_found(error): return '<!DOCTYPE html><html><body><div style="text-align: center;">Page not found</div></body></html>' if __name__ == '__main__': app.run(debug=True, host="0.0.0.0")
修改后的登录页面(改名为login.html,放到templates目录下)
原来的登录代码只需要套上form标签即可,不需要额外加JS脚本:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>登录</title> <link type="text/css" rel="stylesheet" href="materialize.min.css"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> </head> <body> <div> <nav> <div class="nav-wrapper grey darken-4"> <div style="text-align: center; font-size: 30px; font-weight: bold;">商品系统</div> <div class="row"> <div class="col s12 m8 l4 offset-m2 offset-l4"> <br> <br> <div class="card"> <div class="card-content"> <!-- 新增form标签指定提交方法和地址 --> <form method="POST" action="/login"> <div class="row"> <div class="input-field col s12"> <input id="email" name="email" type="email" class="validate" required> <label for="email">Email</label> </div> </div> <div class="row"> <div class="input-field col s12"> <input id="password" name="password" type="password" class="validate" required> <label for="password">Password</label> </div> </div> {% if error %} <div style="color: red; text-align: center; margin-bottom: 10px;">{{ error }}</div> {% endif %} <button type="submit" class="waves-effect waves-light btn blue darken-1" style="width:100%;">Login</button> <br> </form> </div> </div> </div> </div> </div> </nav> </div> </body> </html>
新增商品展示页templates/products.html
按照你的业务需求写商品内容即可,示例参考:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>商品列表</title> </head> <body> <h1>登录成功,商品内容展示区</h1> <a href="/logout">退出登录</a> </body> </html>
部署注意事项
- 生产环境记得把secret_key换成随机字符串,通过环境变量读取不要硬编码在代码里
- K8s Ingress一定要配置HTTPS证书,保证密码传输安全
- 实际使用时用户数据存储在数据库中,不要像示例一样硬编码在代码里
内容的提问来源于stack exchange,提问作者Nav
相关产品推荐
相关产品推荐

