基于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>
相关文章:
基于Flask的通用登录注册模块,并代理跳转到目标网址
实现了用户密码的加密,代理跳转到目标网址,不会暴露目标路径,未登录的情况下访问proxy则自动跳转到登录页,使用时需要修改配置项config,登录注册页面背景快速修改,可以实现登录注册模块的快速复用。 1.app…...
个人学习编程(3-25) leetcode刷题
验证括号字符串: 用了两个栈来存放。 只需要考虑) 优先用 ( 其次用* 即可 #include <bits/stdc.h> using namespace std;bool checkValidString(char* s){int len strlen(s);stack<int> left_stack,star_stack;for (int i 0; i < len; i){if(s[i] (){left_st…...
vue中实现元素在界面中自由拖动
这是一个使用 Vue 2 实现可拖动 div 的示例。 <!DOCTYPE html> <html> <head><title>Vue 2 可拖动 Div</title><script src"https://cdn.jsdelivr.net/npm/vue2.6.14/dist/vue.js"></script><style>#draggable-div…...
量子计算在密码学中的应用:机遇与挑战并存
引言 在数字化时代的浪潮中,密码学作为信息安全的核心技术,始终扮演着至关重要的角色。从保护个人隐私到保障国家机密,密码学的每一次进步都为信息安全筑牢了防线。然而,随着量子计算技术的飞速发展,传统密码学体系面…...
使用go实现导入Rxcel数据到数据库并渲染到页面上
github.com/360EntSecGroup-Skylar/excelize github.com/tealeg/xlsx 可以使用以上两个库 代码如下: // jsonResult 返回 JSON 格式的结果 func (c *TemplateController) jsonResult(code int, msg string, data interface{}) {c.Data["json"] map[s…...
C++中将记录集的数据复制到Excel工作表中的CRange类CopyFromRecordset函数异常怎么捕获
文章目录 一、异常类型及捕获逻辑二、完整代码示例三、关键错误场景与解决方案1. CopyFromRecordset 返回空数据2. COM错误 0x800A03EC3. Excel进程残留4. 内存不足 四、调试与日志记录1. 启用详细日志2. 捕获错误描述3. 调试断点 五、最佳实践 在C中使用 CRange::CopyFromReco…...
使用vector构造杨辉三角形
力扣118题: 给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中,每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]示例 2: 输入: numRows 1…...
conda环境下解决gitk乱码模糊
关键词 conda、git、gitk、git gui、模糊、linux、乱码 现象 操作系统:ubuntu24.04 conda版本:25.1.1 正常的终端里gitk显示不会模糊 但是在conda创建的python虚拟环境中使用gitk,字体开始变得模糊不清 分析 根据deepseek的原因原因分析…...
Contactile三轴触觉传感器:多维力感赋能机器人抓取
在非结构化环境中,机器人对物体的精准抓取与操作始终面临巨大挑战。传统传感器因无法全面感知触觉参数(如三维力、位移、摩擦),难以适应复杂多变的场景。Contactile推出的三轴触觉力传感器,通过仿生设计与创新光学技术…...
远程登录服务(ssh)
一、远程登录服务概述 1. 概念 远程登录服务就像是一个神奇的桥梁,它让你能够跨越物理距离,通过网络连接到另一台计算机上进行操作。无论你身在何处,只要有网络连接,你就可以像坐在目标计算机前一样进行各种操作。 2. 功能 分享…...
如何在阿里云linux主机上部署Node.Js
在阿里云的Linux服务器上搭建Node.js编程环境可以通过以下步骤完成。这里以常见的 Ubuntu/CentOS 系统为例,提供两种安装方式(包管理器、NVM多版本管理): 一、通过包管理器安装(适合快速安装指定版本) 1. …...
VS Code连接远程服务遇到的问题
目录 一、VS Code链接远程服务 二、修改的文件不能保存 三、无法与 "Ip地址" 建立连接: 远程主机密钥已更改,端口转发已禁用. 四、解决远程连接后,每次断开让输入密码问题,实现免密登录 没有秘钥对,免密配置流程&a…...
算法学习第十六天:动态规划(补充题目)
动态规划题 目录 最大乘积子数组股票买卖问题最长递增子序列零钱兑换编辑距离 最大乘积子数组 问题描述 给定一个整数数组,求乘积最大的连续子数组的乘积。 关键点 需要同时记录当前最大值和最小值(负负得正)状态转移方程: …...
最长连续子序列和的所含元素 -- Kadane算法拓展
建议先回顾经典Kadane算法 -- 最长连续子序列和: 最大连续子序列和(动态规划 -- 经典Kadane算法)-CSDN博客 拓展代码: def max_subarray_sum(nums):global_max current_max nums[0]left right temp 0for i in range(1, len(…...
大模型训练 | 智能体知识库 资源收集之心理咨询问答数据集
最近我一直在研究AI大模型相关的内容,想着从现在开始慢慢收集各种各样的资源,万一以后需要训练大模型的时候可以用到,或者自己以后也许会需要。今天我想介绍一组“心理咨询问答数据集”产品,包含9414条心理咨询问答数据࿰…...
AI Agent开发大全第十一课-超维空间里的语义翻译官:Embedding技术
一、Embedding:数字世界的"翻译官"与"导航仪" 1.1 从字符到向量的魔法 当我们输入"巧克力"三个字时,传统计算机只能识别ASCII码组成的符号序列,而Embedding技术就像给每个词语配备了"超维定位坐标"。通过深度学习模型,它将离散的…...
2024年第九届全国固态电池研讨会(脱敏)PPT合集(41份).zip
2024年第九届全国固态电池研讨会(脱敏)PPT合集,共41份。供大家参考学习。 1、锂金属全固态电池关键材料与器件.pdf 2、聚醚基聚合物锂金属电池.pdf 3、氧化物固态电解质与高能量密度安全固态锂电池.pdf 4、复合固态电解质界面设计工艺探索与…...
OpenCV三维解算常用方法C++
如果标定过程是通过OpenCV张正友标定法实现的,得到的内参外参保存在.txt文件中是这样的形式: ① 内参intrinsics.txt: ② 外参extrinsics.txt: 那么可以通过如下方法读取.txt文件获取左右相机内外参,主要包括三维解算…...
JavaScript 类型转换:全面解析与实践
引言 在 JavaScript 编程里,类型转换是一个频繁出现且极为重要的操作。由于 JavaScript 是一种动态类型语言,变量的类型在运行时可以改变,这就使得类型转换变得十分常见。类型转换主要分为隐式类型转换和显式类型转换,下面将详细…...
Qt Concurrent Filter and Filter-Reduce
并行滤波和滤波-还原 QtConcurrent::filter()、QtConcurrent::filtered() 和 QtConcurrent::filedReduced() 函数并行过滤序列中的项目,如QList 。QtConcurrent::filter() 就地修改序列,QtConcurrent::filtered() 返回包含过滤内容的新序列,…...
【蓝桥杯每日一题】3.25
🏝️专栏: 【蓝桥杯备篇】 🌅主页: f狐o狸x “OJ超时不是终点,是算法在提醒你该优化时间复杂度了!” 目录 3.25 差分数组 一、一维差分 题目链接: 题目描述: 解题思路:…...
深挖增长内核:好产品驱动增长的全方位解析
年前在老板的带领下深入学习了《增长黑客》,并思考了在CPS站外引流的落地方案,最近刚好在做京东联盟的京粉推客增长体系建设,再次回顾一下增长黑客方法以及记录一下思考。 好产品才是增长的根本。增长黑客理念风靡,“啊哈时刻” 概…...
Python技术栈与数据可视化创意实践详解(三)
Python在数据可视化领域凭借丰富的库和灵活的生态系统,能够实现从基础图表到复杂交互式可视化的全场景覆盖。以下从技术选型、创意实现到实战优化进行系统化解析,并提供可直接落地的代码示例。 一、Python数据可视化技术栈 1. 基础与统计可视化 Matplotl…...
前端NVM安装
https://v0.dev/chat/settings 本地启动环境 1安装 nvm 2安装node nvm install v18.19.0 nvm install v20.9.0 nvm use 18 node -v 3安装 pnpm npm install -g pnpm 或者 npm i -g pnpm 4启动 代码 目录下 执行 pnpm i pnpm run dev 4.1到代码目录下 4.2直接cmd…...
Springboot应用配置github自动流部署 深入理解CI/CD:构建、测试和部署的自动化完整流程
什么是 CI 持续集成 通过自动化的流程和工具,提高软件开发的效率、质量和交付速度。 持续集成是开发团队通过将代码的不同部分集成到共享存储库中,并频繁地进行构建和测试,以确保代码的一致性和稳定性。 概念 在现在的开发模式中&#x…...
解锁DeepSeek潜能:Docker+Ollama打造本地大模型部署新范式
🐇明明跟你说过:个人主页 🏅个人专栏:《深度探秘:AI界的007》 🏅 🔖行路有良友,便是天堂🔖 目录 一、引言 1、什么是Docker 2、什么是Ollama 二、准备工作 1、操…...
c++R 格式
问题描述 小蓝最近在研究一种浮点数的表示方法:RR 格式。对于一个大于 0 的浮点数 dd,可以用 RR 格式的整数来表示。给定一个转换参数 nn,将浮点数转换为 RR 格式整数的做法是: 将浮点数乘以 2n2n; 四舍五入到最接近的整数。 …...
qt QOffscreenSurface详解
1、概述 QOffscreenSurface 是 Qt 中用于离屏渲染的一个类。它允许在不直接与屏幕交互的情况下进行 OpenGL 渲染操作,常用于生成纹理、预渲染场景等。通过 QOffscreenSurface,可以在后台创建一个渲染表面,进行绘制操作,并将结果捕…...
基于Spring Boot的消防物资存储系统的设计与实现(LW+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...
深度学习算法清单
目录 1. 神经网络必备基础知识点 2. 神经网络前向传播与反向传播 3. 网络模型整体架构分析实例 4. 神经网络建模效果分析 5. 激活函数与过拟合问题解决 6. 卷积神经网络核心知识点 7. 卷积建模流程与各参数作用分析 8. 池化层的作用与效果 9. 经典卷积神经网络架构分析…...
