基于Flask的通用登录注册模块,并代理跳转到目标网址

实现了用户密码的加密,代理跳转到目标网址,不会暴露目标路径,未登录的情况下访问proxy则自动跳转到登录页,使用时需要修改配置项config,登录注册页面背景快速修改,可以实现登录注册模块的快速复用。

1.app.py

from flask import Flask, render_template, request, redirect, url_for, session, Response
import sqlite3
import os
import bcrypt
import requestsapp = Flask(__name__)
app.secret_key = os.urandom(24)# 数据库连接
def get_db():conn = sqlite3.connect('users.db')return conn# 创建用户表
def create_user_table():conn = get_db()c = conn.cursor()c.execute('''CREATE TABLE IF NOT EXISTS users(id INTEGER PRIMARY KEY AUTOINCREMENT,username TEXT NOT NULL UNIQUE,password TEXT NOT NULL)''')conn.commit()conn.close()create_user_table()# 配置项
config = {"after_login_url": "http://xxxx",  # 修改为目标网址"after_register_url": "/login","login_background_image": "static/login_background.jpg","register_background_image": "static/register_background.jpg"
}# 检查用户是否登录的装饰器
def login_required(func):def wrapper(*args, **kwargs):if 'username' not in session:return redirect(url_for('login'))return func(*args, **kwargs)wrapper.__name__ = func.__name__return wrapper# 注册页面
@app.route('/register', methods=['GET', 'POST'])
def register():error = Nonesuccess = Noneif request.method == 'POST':username = request.form.get('username')password = request.form.get('password').encode('utf-8')hashed = bcrypt.hashpw(password, bcrypt.gensalt())conn = get_db()c = conn.cursor()try:c.execute("INSERT INTO users (username, password) VALUES (?,?)", (username, hashed))conn.commit()success = "注册成功!请登录。"except sqlite3.IntegrityError as e:print(f"IntegrityError: {e}")error = "用户名已存在,请选择其他用户名。"finally:conn.close()return render_template('register.html', error=error, success=success,background_image=config["register_background_image"])# 登录页面
@app.route('/login', methods=['GET', 'POST'])
def login():error = Noneif request.method == 'POST':username = request.form.get('username')password = request.form.get('password').encode('utf-8')remember_me = request.form.get('remember_me')conn = get_db()c = conn.cursor()c.execute("SELECT password FROM users WHERE username =?", (username,))user = c.fetchone()conn.close()if user:stored_password = user[0]if bcrypt.checkpw(password, stored_password):session['username'] = usernameif remember_me:session.permanent = Truereturn redirect(url_for('proxy'))error = "用户名或密码错误。"return render_template('login.html', error=error, background_image=config["login_background_image"])# 注销
@app.route('/logout')
def logout():session.pop('username', None)return redirect(url_for('login'))# 代理请求
@app.route('/proxy')
@login_required
def proxy():target_url = config["after_login_url"]try:resp = requests.get(target_url, headers=dict(request.headers))excluded_headers = ['content-encoding', 'content-length', 'transfer-encoding', 'connection']headers = [(name, value) for (name, value) in resp.raw.headers.items()if name.lower() not in excluded_headers]return Response(resp.content, resp.status_code, headers)except requests.RequestException as e:return f"请求出错: {str(e)}", 500# 将根目录设置为跳转到代理路由
@app.route('/')
@login_required
def index():return redirect(url_for('proxy'))if __name__ == '__main__':app.run(debug=True)

2.login.html

<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>登录</title><!-- 使用 url_for 生成 CSS 文件的绝对路径 --><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"><style>body {background-image: url('{{ background_image }}');background-size: cover;background-repeat: no-repeat;background-position: center center;display: flex;justify-content: center;align-items: center;height: 100vh;margin: 0;}.card {border: none;border-radius: 10px;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);transition: all 0.3s ease;background-color: rgba(255, 255, 255, 0.9);}.card:hover {box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);}.card-header {background-color: #0d6efd;color: white;border-top-left-radius: 10px;border-top-right-radius: 10px;}.alert {margin-top: 15px;}</style>
</head><body><div class="container d-flex justify-content-center align-items-center vh-100"><div class="card w-50"><div class="card-header text-center"><h2>登录</h2></div><div class="card-body">{% if error %}<div class="alert alert-danger" role="alert">{{ error }}</div>{% endif %}<form method="post"><div class="mb-3"><label for="username" class="form-label">用户名:</label><input type="text" id="username" name="username" class="form-control" required></div><div class="mb-3"><label for="password" class="form-label">密码:</label><input type="password" id="password" name="password" class="form-control" required></div><div class="form-check mb-3"><input class="form-check-input" type="checkbox" value="1" id="remember_me" name="remember_me"><label class="form-check-label" for="remember_me">记住密码</label></div><button type="submit" class="btn btn-primary w-100">登录</button></form><p class="mt-3 text-center">还没有账号?<a href="{{ url_for('register') }}">注册</a></p></div></div></div><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body></html>

3.register.html

<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>注册</title><!-- 使用 url_for 生成 CSS 文件的绝对路径 --><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"><style>body {background-image: url('{{ background_image }}');background-size: cover;background-repeat: no-repeat;background-position: center center;display: flex;justify-content: center;align-items: center;height: 100vh;margin: 0;}.card {border: none;border-radius: 10px;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);transition: all 0.3s ease;background-color: rgba(255, 255, 255, 0.9);}.card:hover {box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);}.card-header {background-color: #0d6efd;color: white;border-top-left-radius: 10px;border-top-right-radius: 10px;}.alert {margin-top: 15px;}</style>
</head><body><div class="container d-flex justify-content-center align-items-center vh-100"><div class="card w-50"><div class="card-header text-center"><h2>注册</h2></div><div class="card-body">{% if error %}<div class="alert alert-danger" role="alert">{{ error }}</div>{% endif %}{% if success %}<div class="alert alert-success" role="alert">{{ success }}</div>{% endif %}<form method="post"><div class="mb-3"><label for="username" class="form-label">用户名:</label><input type="text" id="username" name="username" class="form-control" required></div><div class="mb-3"><label for="password" class="form-label">密码:</label><input type="password" id="password" name="password" class="form-control" required></div><button type="submit" class="btn btn-primary w-100">注册</button></form><p class="mt-3 text-center">已有账号?<a href="{{ url_for('login') }}">登录</a></p></div></div></div><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body></html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/73779.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java课程设计(双人对战游戏)持续更新......

少废话&#xff0c;当然借助了ai&#xff0c;就这么个实力&#xff0c;后续会逐渐完善...... 考虑添加以下功能&#xff1a; 选将&#xff0c;选图&#xff0c;技能&#xff0c;天赋&#xff0c;道具&#xff0c;防反&#xff0c;反重力&#xff0c;物理反弹&#xff0c;击落…

Ai工作流工具有那些如Dify、coze扣子等以及他们是否开源

Dify &#xff08;https://difycloud.com/&#xff09; 核心定位&#xff1a;专业级 LLM 应用开发平台&#xff0c;支持复杂 AI 工作流构建与企业级管理。典型场景&#xff1a;企业智能客服、数据分析系统、复杂自动化流程构建等。适合需要深度定制、企业级管理和复杂 AI 逻辑…

Debezium系列之:使用Debezium和Apache Iceberg构建数据湖

Debezium系列之:使用Debezium和Apache Iceberg构建数据湖 Debezium Server Iceberg“Debezium Server Iceberg” 消费者设置数据复制Upsert 模式保留已删除的记录使用Upsert模式追加模式优化批处理大小在数据分析的世界中,数据湖是存储和管理大量数据以满足数据分析、报告或机…

docker run -p 5000:5000 my-flask-app

docker run -p 5000:5000 my-flask-app代码的意思是&#xff1a; 运行 my-flask-app 容器&#xff0c;并把 Flask 服务器的 5000 端口映射到本机的 5000 端口。 拆解解释 docker run -p 5000:5000 my-flask-app✅ docker run → 运行一个 Docker 容器 ✅ -p 5000:5000 → 端口…

高光谱工业相机+LED光源系统助力材料分类和异物检测、实现高速在线检测

检测光源包括可见光&#xff0c;如红光、蓝光和绿光以及其他波长的光&#xff0c;如紫外和红外波长&#xff0c;可以选择与检测对象物相应的波长。但由于能够照射的波长较窄&#xff0c;例如受到同色异物混入或多个素材的材质分类等&#xff0c;可能需要使用可照射多种波长的光…

Spring 拦截器(Interceptor)与过滤器(Filter)对比

Spring 拦截器&#xff08;Interceptor&#xff09;与过滤器&#xff08;Filter&#xff09;对比 核心对比表格 对比维度拦截器&#xff08;Interceptor&#xff09;过滤器&#xff08;Filter&#xff09;定义Spring MVC 提供的组件&#xff0c;集成于 Spring 处理器链。Servl…

VulnHub-FALL通关攻略

第一步&#xff1a;确定靶机IP为192.168.40.129 第二步&#xff1a;扫描后台及开放端口 #开放端口 22 --- ssh 25 --- SMTP简单邮件传输协议 80 --- HTTP万维网传输信息协议 110 --- POP3邮件协议3 139 --- NetBIOS服务 443 --- https服务 445 --- SMB协议 3306 --- Mysql 808…

Qt 线程和 QObjects

线程和 QObjects QThread 继承于 QObject。 它发出信号来指示线程开始或结束执行&#xff0c;并提供一些插槽。 更有趣的是&#xff0c;QObjects 可以在多个线程中使用&#xff0c;发出信号以调用其他线程中的插槽&#xff0c;并向 "生活 "在其他线程中的对象发布事件…

华为、浪潮、华三链路聚合概述

1、华为 链路聚合可以提高链路带宽和链路冗余性。有三种类型&#xff0c;分别是手工链路聚合&#xff0c;静态lacp链路聚合&#xff0c;动态lacp链路聚合。 手工链路模式&#xff1a;也称负载分担模式&#xff0c;需手动指定链路&#xff0c;各链路之间平均分担流量。静态LAC…

HarmonyOS NEXT 鸿蒙中关系型数据库@ohos.data.relationalStore API 9+

核心API ohos.data.relationalStore API 9 数据库 数据库是存储和管理数据的系统 数据库&#xff08;Database&#xff09;是一个以特定方式组织、存储和管理数据的集合&#xff0c;通常用于支持各种应用程序和系统的运行。它不仅是存放数据的仓库&#xff0c;还通过一定的…

步进电机 cia402协议 报文自己的理解 (笔记)

1. cai402 协议是什么 CiA 402 协议&#xff08;CAN in Automation 402&#xff09;&#xff0c;它是工业自动化领域中的一种通信协议&#xff0c;主要用于运动控制&#xff08;如伺服驱动器、步进电机等&#xff09;&#xff08; &#xff09;所属标准 CiA 402 是 CANopen 应用…

鸿蒙摄像机,一场智能安防的“平权革命”

2025的春天&#xff0c;全国各行各业都感受到了普惠AI的魅力。大模型带来的技术平权&#xff0c;让每一个人都能轻松用上AI。 这时候&#xff0c;企业想知道&#xff0c;每时每刻离不开的摄像机&#xff0c;究竟什么时候才能迎来智能技术的平权与普惠。 博思数据研究中心的一份…

解决HuggingFaceEmbeddings模型加载报错:缺少sentence-transformers依赖包

遇到报错 报错信息: Error loading model: Could not import sentence_transformers python package. Please install it with pip install sentence-transformers. 装包信息&#xff1a; pip install modelscope langchain sentence_transformers langchain-huggingface on…

从泛读到精读:合合信息文档解析如何让大模型更懂复杂文档

从泛读到精读&#xff1a;合合信息文档解析如何让大模型更懂复杂文档 一、引言&#xff1a;破解文档“理解力”瓶颈二、核心功能&#xff1a;合合信息的“破局”亮点功能亮点1&#xff1a;复杂图表的高精度解析图表解析&#xff1a;为大模型装上精准“标尺”表格数据精准还原 功…

Python+requests实现接口自动化测试框架

为什么要做接口自动化框架 1、业务与配置的分离 2、数据与程序的分离&#xff1b;数据的变更不影响程序 3、有日志功能&#xff0c;实现无人值守 4、自动发送测试报告 5、不懂编程的测试人员也可以进行测试 正常接口测试的流程是什么&#xff1f; 确定接口测试使用的工具…

信息学奥赛一本通 1514:【例 2】最大半连通子图 | 洛谷 P2272 [ZJOI2007] 最大半连通子图

【题目链接】 ybt 1514&#xff1a;【例 2】最大半连通子图 洛谷 P2272 [ZJOI2007] 最大半连通子图 【题目考点】 1. 图论&#xff1a;强连通分量 缩点 2. 图论&#xff1a;拓扑排序 有向无环图动规 【解题思路】 对于图中任意两顶点u、v&#xff0c;满足u到v或v到u有路径…

Android打aar包问题总结

1、moduleA 依赖 moduleB&#xff0c;将moduleA打包成aar时&#xff0c;未包含 moduleB的resources资源&#xff1b; 方法一&#xff1a;将moduleB的资源&#xff0c;手动拷贝一份到moduleA中&#xff1b; 方法二&#xff1a;使用 fat-aar 插件&#xff1b; 2、fat-aar插件使…

【网络协议】【http】http 简单介绍

【网络协议】【http】http 简单介绍 1 HTTP 头部 HTTP 是一种请求-响应协议&#xff0c;客户端向服务器发送请求&#xff0c;服务器返回响应。 1.1 HTTP 状态码 状态码是服务器返回给客户端的 三位数字代码&#xff0c;用于表示请求的执行结果。 状态码按照首位数字分类&am…

谈谈空间复杂度考量,特别是递归调用栈空间消耗?

空间复杂度考量是算法设计的核心要素之一&#xff0c;递归调用栈的消耗问题在前端领域尤为突出。 以下结合真实开发场景进行深度解析&#xff1a; 一、递归调用栈的典型问题 1. 深层次DOM遍历的陷阱 // 危险操作&#xff1a;递归遍历未知层级的DOM树 function countDOMNode…

LeetCode算法题(Go语言实现)_16

题目 给定一个二进制数组 nums 和一个整数 k&#xff0c;假设最多可以翻转 k 个 0 &#xff0c;则返回执行操作后 数组中连续 1 的最大个数 。 一、代码实现 func longestOnes(nums []int, k int) int {left, zeroCnt, maxLen : 0, 0, 0for right : 0; right < len(nums); …