当前位置: 首页 > news >正文

Flask Session 登录认证模块

Flask 框架提供了强大的 Session 模块组件,为 Web 应用实现用户注册与登录系统提供了方便的机制。结合 Flask-WTF 表单组件,我们能够轻松地设计出用户友好且具备美观界面的注册和登录页面,使这一功能能够直接应用到我们的项目中。本文将深入探讨如何通过 Flask 和 Flask-WTF 构建一个完整的用户注册与登录系统,以及如何对页面进行优化美化,提高用户体验。通过这一系统,用户能够方便注册账户、安全登录,并且我们能够有效管理用户的会话信息,为 Web 应用的用户管理提供一种高效的解决方案。

什么是Session机制?

Session 是一种在 Web 应用中用于存储用户特定信息的机制。它允许在用户访问网站时存储和检索信息,以便在用户的不同请求之间保持状态。Session 机制在用户登录、购物网站、个性化设置等场景中得到广泛应用,它为用户提供了更加连贯和个性化的体验。在 Flask 中,通过 Flask Session 模块可以方便地使用 Session ,实现用户状态的维护和管理。

在 Web 开发中,HTTP 协议是无状态的,即每个请求都是独立的,服务器不会记住之前的请求信息。为了解决这个问题,引入了 Session 机制。基本思想是在用户访问网站时,服务器生成一个唯一的 Session ID,并将这个 ID 存储在用户的浏览器中(通常通过 Cookie)。同时,服务器端会保存一个映射,将 Session ID 与用户的相关信息关联起来,这样在用户的后续请求中,服务器就能根据 Session ID 找到相应的用户信息,从而实现状态的保持。

Session 的认证流程通常包括以下步骤:

  1. 用户登录: 用户通过提供用户名和密码进行登录。在登录验证成功后,服务器为该用户创建一个唯一的 Session ID,并将这个 ID 存储在用户浏览器的 Cookie 中。
  2. Session 存储: 服务器端将用户的相关信息(如用户 ID、权限等)与 Session ID 关联起来,并将这些信息存储在服务器端的 Session 存储中。Session 存储可以是内存、数据库或其他持久化存储方式。
  3. Session ID 传递: 服务器将生成的 Session ID 发送给用户浏览器,通常是通过 Set-Cookie 头部。这个 Cookie 会在用户的每次请求中被包含在 HTTP 头中。
  4. 后续请求: 用户在后续的请求中会携带包含 Session ID 的 Cookie。服务器通过解析请求中的 Session ID,从 Session 存储中检索用户的信息,以恢复用户的状态。
  5. 认证检查: 服务器在每次请求中检查 Session ID 的有效性,并验证用户的身份。如果 Session ID 无效或过期,用户可能需要重新登录。
  6. 用户登出: 当用户主动注销或 Session 过期时,服务器将删除与 Session ID 关联的用户信息,用户需要重新登录。

总体而言,Session 的认证流程通过在客户端和服务器端之间传递唯一的 Session ID,实现了用户状态的持久化和管理。这种机制使得用户可以在多个请求之间保持登录状态,提供了一种有效的用户认证方式。在 Flask 中,开发者可以方便地使用 Flask 提供的 Session 模块来实现这一流程。

Session 认证基础

默认情况下,直接使用Session模块即可实现Session登录会话保持,该方式是将Session存储到内存中,程序重启后即释放,Session的设置一般可以通过使用session["username"]赋值的方式进行,如需验证该Session的可靠性,则只需要调用session.get方法即可一得到特定字段,通过对字段的判断即可实现认证机制。

如下是一个Flask后端代码,运行后通过访问http://127.0.0.1:5000进入到登录这页面。

from flask import Flask,session,render_template,request,Response,redirect,url_for
from functools import wraps
import osapp = Flask(__name__, static_folder="./template",template_folder="./template")
app.config['SECRET_KEY'] = os.urandom(24)# 登录认证装饰器
def login_required(func):@wraps(func)def wrapper(*args, **kwargs):if session.get("username") != None and session.get("is_login") ==True:print("登陆过则继续执行原函数")return func(*args, **kwargs)else:print("没有登录则跳转到登录页面")resp = Response()resp.status_code=200resp.data = "<script>window.location.href='/login';</script>"return respreturn wrapper@app.route("/login",methods=["GET","POST"])
def login():if request.method == "GET":html = """<form action="/login" method="post"><p>账号: <input type="text" name="username"></p><p>密码: <input type="password" name="password"></p><input type="submit" value="登录"></form>"""return htmlif request.method == "POST":get_dict = request.form.to_dict()get_username = get_dict['username']get_password = get_dict['password']if (get_username == "lyshark" or get_username == "admin") and get_password == "123123":session["username"] = get_usernamesession["is_login"] = Trueprint("登录完成直接跳到主页")resp = Response()resp.status_code=200resp.data = "<script>window.location.href='/index';</script>"return respelse:return "登陆失败"return "未知错误"# 主页菜单
@app.route("/index",methods = ["GET","POST"])
@login_required
def index():username = session.get("username")return "用户 {} 您好,这是主页面".format(username)# 第二个菜单
@app.route("/get",methods = ["GET","POST"])
@login_required
def get():username = session.get("username")return "用户 {} 您好,这是子页面".format(username)@app.route("/logout",methods = ["GET","POST"])
@login_required
def logout():username = session.get("username")# 登出操作session.pop("username")session.pop("is_login")session.clear()return "用户 {} 已注销".format(username)if __name__ == '__main__':app.run()

程序运行后,当用户访问http://127.0.0.1:5000地址则会跳转到login登陆页面,此时如果用户第一次访问则会输出如下所示的登陆信息;

通过输入正确的用户名lyshark和密码123123则可以登录成功,此处登录的用户是lyshark如下图。

通过输入不同的用户登录会出现不同的页面提示信息,如下图则是admin的主页信息。

当我们手动输入logout时则此时会退出登录用户,后台也会清除该用户的Session,在开发中可以自动跳转到登出页面;

Session 使用数据库

通过结合 Session 与 SQLite 数据库,我们可以实现一个更完善的用户注册、登录以及密码修改功能。在这个案例中,首先,用户可以通过注册表单输入用户名、密码等信息,这些信息经过验证后将被存储到 SQLite 数据库中。注册成功后,用户可以使用相同的用户名和密码进行登录。登录成功后,我们使用 Flask 的 Session 机制将用户信息保存在服务器端,确保用户在访问其他页面时仍然处于登录状态。

为了增加更多功能,我们还可以实现密码修改的功能。用户在登录状态下,通过密码修改表单输入新的密码,我们将新密码更新到数据库中,确保用户可以安全地更改密码。这个案例综合运用了 Flask、SQLite 和 Session 等功能,为 Web 应用提供了一套完整的用户管理系统。

from flask import Flask,request,render_template,session,Response
import sqlite3,os
from functools import wrapsapp = Flask(__name__)app.config['SECRET_KEY'] = os.urandom(24)# 创建数据库
def UserDB():conn = sqlite3.connect("./database.db")cursor = conn.cursor()create = "create table UserDB(" \"uid INTEGER primary key AUTOINCREMENT not null unique," \"username char(64) not null unique," \"password char(64) not null," \"email char(64) not null" \")"cursor.execute(create)conn.commit()cursor.close()conn.close()# 增删改查简单封装
def RunSqlite(db,table,action,field,value):connect = sqlite3.connect(db)cursor = connect.cursor()# 执行插入动作if action == "insert":insert = f"insert into {table}({field}) values({value});"if insert == None or len(insert) == 0:return Falsetry:cursor.execute(insert)except Exception:return False# 执行更新操作elif action == "update":update = f"update {table} set {value} where {field};"if update == None or len(update) == 0:return Falsetry:cursor.execute(update)except Exception:return False# 执行查询操作elif action == "select":# 查询条件是否为空if value == "none":select = f"select {field} from {table};"else:select = f"select {field} from {table} where {value};"try:ref = cursor.execute(select)ref_data = ref.fetchall()connect.commit()connect.close()return ref_dataexcept Exception:return False# 执行删除操作elif action == "delete":delete = f"delete from {table} where {field};"if delete == None or len(delete) == 0:return Falsetry:cursor.execute(delete)except Exception:return Falsetry:connect.commit()connect.close()return Trueexcept Exception:return False# 创建数据库
@app.route("/create")
def create():UserDB()return "create success"# 登录认证装饰器
def login_required(func):@wraps(func)def wrapper(*args, **kwargs):if session.get("username") != None and session.get("is_login") ==True:print("登陆过则继续执行原函数")return func(*args, **kwargs)else:print("没有登录则跳转到登录页面")resp = Response()resp.status_code=200resp.data = "<script>window.location.href='/login';</script>"return respreturn wrapper# 用户注册页面
@app.route("/register",methods=["GET","POST"])
def register():if request.method == "GET":html = """<form action="/register" method="post"><p>账号: <input type="text" name="username"></p><p>密码: <input type="password" name="password"></p><p>邮箱: <input type="text", name="email"></p><input type="submit" value="用户注册"></form>"""return htmlif request.method == "POST":username = request.form.get("username")password = request.form.get("password")email = request.form.get("email")if RunSqlite("database.db","UserDB","select","username",f"username='{username}'") == []:insert = RunSqlite("database.db","UserDB","insert","username,password,email",f"'{username}','{password}','{email}'")if insert == True:return "创建完成"else:return "创建失败"else:return "用户存在"return "未知错误"# 用户登录模块
@app.route("/login",methods=["GET","POST"])
def login():if request.method == "GET":html = """<form action="/login" method="post"><p>账号: <input type="text" name="username"></p><p>密码: <input type="password" name="password"></p><input type="submit" value="登录"></form>"""return htmlif request.method == "POST":username = request.form.get("username")password = request.form.get("password")select = RunSqlite("database.db","UserDB","select","username,password",f"username='{username}'")if select != []:# 继续验证密码if select[0][1] == password:session["username"] = usernamesession["is_login"] = Trueprint("登录完成直接跳到主页")resp = Response()resp.status_code = 200resp.data = "<script>window.location.href='/index';</script>"return respelse:return "密码不正确"else:return "用户不存在"return "未知错误"# 修改密码
@app.route("/modify",methods=["GET","POST"])
@login_required
def modify():if request.method == "GET":html = """<form action="/modify" method="post"><p>新密码: <input type="password" name="new_password"></p><input type="submit" value="修改密码"></form>"""return htmlif request.method == "POST":username = session.get("username")new_password = request.form.get("new_password")update = RunSqlite("database.db","UserDB","update",f"username='{username}'",f"password='{new_password}'")if update == True:# 登出操作session.pop("username")session.pop("is_login")session.clear()print("密码已更新,请重新登录")resp = Response()resp.status_code = 200resp.data = "<script>window.location.href='/login';</script>"return respelse:return "密码更新失败"return "未知错误"# 主页菜单
@app.route("/index",methods = ["GET","POST"])
@login_required
def index():username = session.get("username")return "用户 {} 您好,这是主页面".format(username)# 第二个菜单
@app.route("/get",methods = ["GET","POST"])
@login_required
def get():username = session.get("username")return "用户 {} 您好,这是子页面".format(username)@app.route("/logout",methods = ["GET","POST"])
@login_required
def logout():username = session.get("username")# 登出操作session.pop("username")session.pop("is_login")session.clear()return "用户 {} 已注销".format(username)if __name__ == '__main__':app.run(debug=True)

案例被运行后首先通过调用http://127.0.0.1:5000/create创建database.db数据库,接着我们可以通过访问/register路径实现账号注册功能,如下我们注册lyshark密码是123123,输出效果如下所示;

通过访问/modify可实现对用户密码的修改,但在修改之前需要先通过/login页面登录后进行,否则会默认跳转到用户登录页面中;

使用WTForms登录模板

在如上代码基础上,我们着重增加一个美化登录模板,以提升用户在注册登录流程中的整体体验。通过引入WTF表单组件和Flask-WTF扩展,在前端实现了一个更友好的登录页面。

此登录模板的设计考虑了页面布局、颜色搭配、表单样式等因素,以确保用户在输入用户名和密码时感到轻松自然。同时,我们利用Flask-WTF的验证器功能,对用户输入的数据进行有效性检查,保障了用户信息的安全性。

首先,我们需要在template目录下,创建register.html前端文件,用于用户注册,并写入以下代码。

<html>
<head><link rel="stylesheet" href="https://www.lyshark.com/javascript/bootstrap/3.3.7/css/bootstrap.min.css"><link href="https://www.lyshark.com/javascript/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" /><link href="https://www.lyshark.com/javascript/other/my_login.css" rel="stylesheet" type="text/css" />
</head>
<body><div class="container"><div class="row"><div class="col-md-offset-3 col-md-6"><form action="/register" method="post" class="form-horizontal">{{ form.csrf_token }}<span class="heading">用 户 注 册</span><div class="form-group">{{ form.username }}<i class="fa fa-user"></i><a href="/login" class="fa fa-question-circle"></a></div><div class="form-group">{{ form.email }}<i class="fa fa-envelope"></i></div><div class="form-group">{{ form.password }}<i class="fa fa-lock"></i></div><div class="form-group">{{ form.RepeatPassword }}<i class="fa fa-unlock-alt"></i></div>{{ form.submit }}</form></div></div></div>
</body>
</html>

接着,继续创建login.html前端文件,用于登录账号时使用,并写入以下代码。

<html>
<head><link rel="stylesheet" href="https://www.lyshark.com/javascript/bootstrap/3.3.7/css/bootstrap.min.css"><link href="https://www.lyshark.com/javascript/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" /><link href="https://www.lyshark.com/javascript/other/my_login.css" rel="stylesheet" type="text/css" />
</head><body><div class="container"><div class="row"><div class="col-md-offset-3 col-md-6"><form action="/login" method="post" class="form-horizontal">{{ form.csrf_token }}<span class="heading">用 户 登 录</span><div class="form-group">{{ form.username }}<i class="fa fa-user"></i></div><div class="form-group help">{{ form.password }}<i class="fa fa-lock"></i><a href="#" class="fa fa-question-circle"></a></div><div class="form-group"><button type="submit" class="btn btn-success">登 录 后 台</button></div></form></div></div></div></body>
</html>

后台代码部分,我们需要在原代码的基础之上,增加对前端注册和登录页面的渲染类,此处使用flask_wtf组件实现渲染生成,具体代码如下。

from flask import Flask,request,render_template,session,Response
from functools import wraps
import sqlite3,osfrom flask_wtf import FlaskForm
from wtforms import widgets,validators
from wtforms.validators import DataRequired,Regexp,DataRequired, Length, Email, EqualTo, NumberRange
from wtforms.fields import (StringField, PasswordField, DateField, BooleanField,DateTimeField,TimeField,SelectField, SelectMultipleField, TextAreaField,FloatField,HiddenField,RadioField, IntegerField, DecimalField, SubmitField, IntegerRangeField)# app = Flask(__name__, static_folder="./template",template_folder="./template")
app = Flask(__name__)app.config["SECRET_KEY"] = "d3d3Lmx5c2hhcmsuY29t"# -----------------------------------------------------------------------------
# 创建数据库
def UserDB():conn = sqlite3.connect("database.db")cursor = conn.cursor()create = "create table UserDB(" \"uid INTEGER primary key AUTOINCREMENT not null unique," \"username char(64) not null unique," \"password char(64) not null," \"email char(64) not null" \")"cursor.execute(create)conn.commit()cursor.close()conn.close()# 增删改查简单封装
def RunSqlite(db,table,action,field,value):connect = sqlite3.connect(db)cursor = connect.cursor()# 执行插入动作if action == "insert":insert = f"insert into {table}({field}) values({value});"if insert == None or len(insert) == 0:return Falsetry:cursor.execute(insert)except Exception:return False# 执行更新操作elif action == "update":update = f"update {table} set {value} where {field};"if update == None or len(update) == 0:return Falsetry:cursor.execute(update)except Exception:return False# 执行查询操作elif action == "select":# 查询条件是否为空if value == "none":select = f"select {field} from {table};"else:select = f"select {field} from {table} where {value};"try:ref = cursor.execute(select)ref_data = ref.fetchall()connect.commit()connect.close()return ref_dataexcept Exception:return False# 执行删除操作elif action == "delete":delete = f"delete from {table} where {field};"if delete == None or len(delete) == 0:return Falsetry:cursor.execute(delete)except Exception:return Falsetry:connect.commit()connect.close()return Trueexcept Exception:return False# -----------------------------------------------------------------------------
# 生成用户注册表单
class RegisterForm(FlaskForm):username = StringField(validators=[DataRequired(message='用户名不能为空'),Length(min=1, max=15, message='用户名长度必须大于%(min)d且小于%(max)d')],widget=widgets.TextInput(),render_kw={'class': 'form-control', "placeholder":"输入注册用户名"})email = StringField(validators=[validators.DataRequired(message='邮箱不能为空'),validators.Email(message="邮箱格式输入有误")],render_kw={'class':'form-control', "placeholder":"输入Email邮箱"})password = PasswordField(validators=[validators.DataRequired(message='密码不能为空'),validators.Length(min=5, message='用户名长度必须大于%(min)d'),validators.Regexp(regex="[0-9a-zA-Z]{5,}",message='密码不允许使用特殊字符')],widget=widgets.PasswordInput(),render_kw={'class': 'form-control', "placeholder":"输入用户密码"})RepeatPassword = PasswordField(validators=[validators.DataRequired(message='密码不能为空'),validators.Length(min=5, message='密码长度必须大于%(min)d'),validators.Regexp(regex="[0-9a-zA-Z]{5,}",message='密码不允许使用特殊字符'),validators.EqualTo("password",message="两次密码输入必须一致")],widget=widgets.PasswordInput(),render_kw={'class': 'form-control', "placeholder":"再次输入密码"})submit = SubmitField(label="用 户 注 册", render_kw={ "class":"btn btn-success" })# 生成用户登录表单
class LoginForm(FlaskForm):username = StringField(validators=[validators.DataRequired(message=''),validators.Length(min=4, max=15, message=''),validators.Regexp(regex="[0-9a-zA-Z]{4,15}", message='')],widget=widgets.TextInput(),render_kw={"class":"form-control", "placeholder":"请输入用户名或电子邮件"})password = PasswordField(validators=[validators.DataRequired(message=''),validators.Length(min=5, max=15,message=''),validators.Regexp(regex="[0-9a-zA-Z]{5,15}",message='')],widget=widgets.PasswordInput(),render_kw={"class":"form-control", "placeholder":"请输入密码"})# -----------------------------------------------------------------------------
# 创建数据库
@app.route("/create")
def create():UserDB()return "create success"# 登录认证装饰器
def login_required(func):@wraps(func)def wrapper(*args, **kwargs):if session.get("username") != None and session.get("is_login") ==True:print("登陆过则继续执行原函数")return func(*args, **kwargs)else:print("没有登录则跳转到登录页面")resp = Response()resp.status_code=200resp.data = "<script>window.location.href='/login';</script>"return respreturn wrapper# 用户注册页面
@app.route("/register",methods=["GET","POST"])
def register():form = RegisterForm(csrf_enabled = True)if request.method == "POST":if form.validate_on_submit():username = form.username.datapassword = form.RepeatPassword.dataemail = form.email.dataprint("用户: {} 邮箱: {}".format(username,email))if RunSqlite("database.db", "UserDB", "select", "username", f"username='{username}'") == []:insert = RunSqlite("database.db", "UserDB", "insert", "username,password,email",f"'{username}','{password}','{email}'")if insert == True:return "创建完成"else:return "创建失败"else:return "用户存在"return render_template("register.html", form=form)# 用户登录页面
@app.route("/login",methods=["GET","POST"])
def login():form = LoginForm(csrf_enabled = True)if request.method == "POST":username = form.username.datapassword = form.password.dataselect = RunSqlite("database.db","UserDB","select","username,password",f"username='{username}'")if select != []:# 继续验证密码if select[0][1] == password:session["username"] = usernamesession["is_login"] = Trueprint("登录完成直接跳到主页")resp = Response()resp.status_code = 200resp.data = "<script>window.location.href='/index';</script>"return respelse:return "密码不正确"else:return "用户不存在"return render_template("login.html", form=form)# 修改密码
@app.route("/modify",methods=["GET","POST"])
@login_required
def modify():if request.method == "GET":html = """<form action="/modify" method="post"><p>新密码: <input type="password" name="new_password"></p><input type="submit" value="修改密码"></form>"""return htmlif request.method == "POST":username = session.get("username")new_password = request.form.get("new_password")update = RunSqlite("database.db","UserDB","update",f"username='{username}'",f"password='{new_password}'")if update == True:# 登出操作session.pop("username")session.pop("is_login")session.clear()print("密码已更新,请重新登录")resp = Response()resp.status_code = 200resp.data = "<script>window.location.href='/login';</script>"return respelse:return "密码更新失败"return "未知错误"# 主页菜单
@app.route("/index",methods = ["GET","POST"])
@login_required
def index():username = session.get("username")return "用户 {} 您好,这是主页面".format(username)# 第二个菜单
@app.route("/get",methods = ["GET","POST"])
@login_required
def get():username = session.get("username")return "用户 {} 您好,这是子页面".format(username)@app.route("/logout",methods = ["GET","POST"])
@login_required
def logout():username = session.get("username")# 登出操作session.pop("username")session.pop("is_login")session.clear()return "用户 {} 已注销".format(username)if __name__ == '__main__':app.run(debug=True)

目录结果如下图所示;

当用户访问/register时,则可以看到通过flask_wtf渲染后的用户注册页面,如下图所示;

用户访问/login时,则是用户登录页面,如下图所示;

相关文章:

Flask Session 登录认证模块

Flask 框架提供了强大的 Session 模块组件&#xff0c;为 Web 应用实现用户注册与登录系统提供了方便的机制。结合 Flask-WTF 表单组件&#xff0c;我们能够轻松地设计出用户友好且具备美观界面的注册和登录页面&#xff0c;使这一功能能够直接应用到我们的项目中。本文将深入探…...

【运维】hive 高可用详解: Hive MetaStore HA、hive server HA原理详解;hive高可用实现

文章目录 一. hive高可用原理说明1. Hive MetaStore HA2. hive server HA 二. hive高可用实现1. 配置2. beeline链接测试3. zookeeper相关操作 一. hive高可用原理说明 1. Hive MetaStore HA Hive元数据存储在MetaStore中&#xff0c;包括表的定义、分区、表的属性等信息。 hi…...

C#开发的OpenRA游戏之属性SelectionDecorations(13)

C#开发的OpenRA游戏之属性SelectionDecorations(13) 在前面分析SelectionDecorations属性类时,会发现它有下面这个属性: public class SelectionDecorations : SelectionDecorationsBase, IRender { readonly Interactable interactable; 它是定义了一个Interactabl…...

接手了一个外包开发的项目,我感觉我的头快要裂开了~

嗨&#xff0c;大家好&#xff0c;我是飘渺。 最近&#xff0c;我和小伙伴一起接手了一个由外包团队开发的微服务项目&#xff0c;这个项目采用了当前流行的Spring Cloud Alibaba微服务架构&#xff0c;并且是基于一个“大名鼎鼎”的微服务开源脚手架&#xff08;附带着模块代…...

git常规使用方法,常规命令

Git是一种分布式版本控制系统&#xff0c;它可以记录软件的历史版本&#xff0c;并提供了多人协作开发、版本回退等功能。以下是Git的基本使用方法&#xff1a; 安装Git&#xff1a;下载安装包并进行安装&#xff0c;安装完成后在命令行中输入 git --version 进行验证。 初始化…...

【JavaScript】3.3 JavaScript工具和库

文章目录 1. 包管理器2. 构建工具3. 测试框架4. JavaScript 库总结 在你的 JavaScript 开发之旅中&#xff0c;会遇到许多工具和库。这些工具和库可以帮助你更有效地编写和管理代码&#xff0c;提高工作效率。在本章节中&#xff0c;我们将探讨一些常见的 JavaScript 工具和库&…...

开发基于 ChatGPT 分析热点事件并生成文章的网站应用【热点问天】把百度等热点用chatGPT来对热点事件分析海量发文章 开发步骤 多种方式获取利润

这样做的优点&#xff1a; 1.不用每个人都问chatGPT同样的问题。 2.已经生成的&#xff0c;反应快速。 3.内容分析的客观&#xff0c;真实&#xff0c;基于数据&#xff0c;无法造假。 4.无其它目的这种基于 ChatGPT 分析热点事件并生成文章的网站&#xff0c;可以通过多种方式…...

龙迅LT8668SXC适用于TPYE-C/DP/HDMI转EDP/VBO同时环出一路HDMI/DP,支持分辨率缩放功能。

1.描述 应用功能&#xff1a;LT8668SXC适用于TYPE-C/DP1.4/HDMI2.1转EDP/VBO同时环出一路HDMI/DP应用方案 分辨率&#xff1a;高达8K30HZ&#xff0c; 工作温度范围&#xff1a;−40C to 85C 产品封装&#xff1a;QFN88 (10*10)最小包装数&#xff1a;1680pcs 2.产品应用 •视频…...

跳板机原理

跳板机原理 跳板机&#xff08;Jump Server&#xff09;是一种网络安全设备或计算机&#xff0c;用于管理和保护内部网络中的其他计算机或系统。跳板机通常位于内部网络和外部网络之间&#xff0c;充当连接这两个网络的中间节点或跳板。以下是跳板机的主要功能和用途&#xff1…...

璞华大数据产品入选中国信通院“铸基计划”

武汉璞华大数据技术有限公司HawkEye设备数字化管理平台产品&#xff0c;凭借优秀的产品技术能力&#xff0c;通过评估后&#xff0c;入选中国信通院“铸基计划”《高质量数字化转型产品及服务全景图&#xff08;2023&#xff09;》的工业数字化领域。 “铸基计划”是中国信通院…...

1146. 新的开始,prim算法,超级原点

发展采矿业当然首先得有矿井&#xff0c;小 FF 花了上次探险获得的千分之一的财富请人在岛上挖了 n 口矿井&#xff0c;但他似乎忘记了考虑矿井供电问题。 为了保证电力的供应&#xff0c;小 FF 想到了两种办法&#xff1a; 在矿井 i 上建立一个发电站&#xff0c;费用为 vi&…...

HTTP常见响应码

HTTP&#xff08;Hypertext Transfer Protocol&#xff09;是用于在客户端和服务器之间传输资源的协议。HTTP响应码&#xff08;HTTP status code&#xff09;用来表示服务器对请求的处理结果。以下是常见的HTTP响应码及其概要&#xff1a; 1. 响应码大类&#xff1a; 主要分…...

物联网边缘计算是什么?如何实现物联网边缘计算?

物联网边缘计算是一种在物联网设备和网络中实施计算和数据处理的技术。它允许在物联网设备或网络边缘进行数据分析和处理&#xff0c;而不需要将所有数据传输到远程数据中心或云端进行处理。物联网边缘计算将计算和数据处理的能力迁移到物联网设备的边缘&#xff0c;使得设备能…...

带着GPT-4V(ision)上路,自动驾驶新探索

On the Road with GPT-4V(ision): Early Explorations of Visual-Language Model on Autonomous Driving GitHub | https://github.com/PJLab-ADG/GPT4V-AD-Exploration arXiv | https://arxiv.org/abs/2311.05332 自动驾驶技术的追求取决于对感知、决策和控制系统的复杂集成。…...

19. Python 数据处理之 Pandas

目录 1. 认识 Pandas2. 安装和导入 Pandas3. Pandas 数据结构4. Pandas 基本功能5. Pandas 数据分析 1. 认识 Pandas Pandas 是 Python 的核心数据分析支持库&#xff0c;提供了快速、灵活、明确的数据结构&#xff0c;旨在简单、直观地处理关系型、标记型数据。 Pandas 的出…...

【计网 可靠数据传输RDT】 中科大笔记 (十 一)

目录 0 引言1 RDT的原理RDT的原理&#xff1a; 2 RDT的机制与作用2.1 重要协议停等协议&#xff08;Stop-and-Wait&#xff09;:连续ARQ协议: 2.2 机制与作用实现机制&#xff1a;RDT的作用&#xff1a; &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#x…...

ubuntu下训练自己的yolov5数据集

参考文档 yolov5-github yolov5-github-训练文档 csdn训练博客 一、配置环境 1.1 安装依赖包 前往清华源官方地址 选择适合自己的版本替换自己的源 # 备份源文件 sudo cp /etc/apt/sources.list /etc/apt/sources.list_bak # 修改源文件 # 更新 sudo apt update &&a…...

ROC及曲线面积汇总学习

目录 ROC基础 生成模拟数据 率的计算 R语言计算测试 ROCR&#xff1a; pROC ROC绘制 单个ROC 两个ROC Logistic回归的ROC曲线 timeROC ROC基础 ROC曲线的横坐标是假阳性率&#xff0c;纵坐标是真阳性率&#xff0c;需要的结果是这个率表示疾病阳性的率&#xff08;…...

LeetCode Hot100 35.搜索插入位置

题目&#xff1a; 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 方法&#xff1a;灵神 二分查找 闭区间写法 c…...

Android frameworks 开发总结之八

Quick Settings增加一項 XXX device要求在quick settings中增加一項touch panel. 在/frameworks/base/packages/SystemUI/res/values/config.xml文件中的quick_settings_tiles_default string 中增加touch panel。並在String resource文件中增加顯示的title <!-- The def…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时&#xff0c;Again增益0db变化为6DB&#xff0c;画面的变化只有2倍DN的增益&#xff0c;比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析&#xff1a; 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库&#xff0c;提供了高效、安全的文本格式化功能&#xff0c;是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...

Python 高效图像帧提取与视频编码:实战指南

Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...

基于鸿蒙(HarmonyOS5)的打车小程序

1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...