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

Django教程第4章 | Web开发实战-三种验证码实现

系列:Django学习教程

验证码的存在是为了防止系统被暴力破解攻击,几乎每个系统都有验证码。下面将介绍三种生成验证码方式。

您可以根据你自己的需要进行学习。

手动生成验证码

安装绘图依赖,利用的是画图模块 PIL 以及随机模块 random 在后台生成一个图片和一串随机数,然后保存在内存中。

pip install pillow

编写跨图工具

code.py

注意需要指定 Monaco.ttf 字体 ,我这里直接放在项目根目录:font_file='Monaco.ttf'

import random
from PIL import Image, ImageDraw, ImageFont, ImageFilterdef check_code(width=120, height=30, char_length=5, font_file='Monaco.ttf', font_size=28):code = []img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255))draw = ImageDraw.Draw(img, mode='RGB')def rndChar():"""生成随机字母:return:"""# return str(random.randint(0, 9))return chr(random.randint(65, 90))def rndColor():"""生成随机颜色:return:"""return (random.randint(0, 255), random.randint(10, 255), random.randint(64, 255))# 写文字font = ImageFont.truetype(font_file, font_size)for i in range(char_length):char = rndChar()code.append(char)h = random.randint(0, 4)draw.text([i * width / char_length, h], char, font=font, fill=rndColor())# 写干扰点for i in range(40):draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())# 写干扰圆圈for i in range(40):draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())x = random.randint(0, width)y = random.randint(0, height)draw.arc((x, y, x + 4, y + 4), 0, 90, fill=rndColor())# 画干扰线for i in range(5):x1 = random.randint(0, width)y1 = random.randint(0, height)x2 = random.randint(0, width)y2 = random.randint(0, height)draw.line((x1, y1, x2, y2), fill=rndColor())img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)return img, ''.join(code)if __name__ == '__main__':img, code_str = check_code()print(code_str)

编写视图函数

views.py

LoginForm类:配置登录表单,涵盖用户名、密码和验证码。返回给模板HTML用于渲染页面。

image_code 函数:调用pillow函数,生成图片,设置60秒写入到自己的session中(以便于后续获取验证码再进行校验)

login函数:验证码这块代码主要是校验从前端传过来的验证码是否跟存在session中的验证码一致,如果一直则继续执行下面代码。否则抛出验证码错误异常。

class LoginForm(BootstrapForm):username = forms.CharField(label="用户名",widget=forms.TextInput,required=True)password = forms.CharField(label="密码",widget=forms.PasswordInput(render_value=True),required=True,)code = forms.CharField(label="验证码",widget=forms.TextInput,required=True)def image_code(request):""" 生成图片验证码 """# 调用pillow函数,生成图片img, code_string = check_code()# 写入到自己的session中(以便于后续获取验证码再进行校验)request.session['image_code'] = code_string# 给Session设置60s超时request.session.set_expiry(60)stream = BytesIO()img.save(stream, 'png')return HttpResponse(stream.getvalue())def login(request):if request.method == 'GET':form = LoginForm()return render(request, 'login.html', {'form': form})form = LoginForm(data = request.POST)if form.is_valid():# 验证码的校验user_input_code = form.cleaned_data.pop('code')code = request.session.get('image_code', "")if code.upper() != user_input_code.upper():form.add_error("code", "验证码错误")return render(request, 'login.html', {'form': form})# 查询数据库匹配用户名密码是否正确user_obj = models.UserInfo.objects.filter(**form.cleaned_data).first()print(user_obj)if not user_obj:form.add_error('password', '用户名或密码错误')return render(request, 'login.html', {'form': form})request.session['info'] = {'id': user_obj.id, 'username': user_obj.username}# 设置 session 过期时间为30分钟request.session.set_expiry(60 * 30)return redirect('/user/list/')return render(request, 'login.html', {'form': form})

login.html

{{ form.code }}:验证码。
{{ form.code.errors.0 }}:验证码输出错误时返回错误提示。

img 标签设置 onclick事件,当用户单击验证码图片生成一个新的验证码。
相当于向服务器发送请求:http://localhost:8000/image/code/?temp=随机数

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>用户管理系统</title><link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}"><style>.account {width: 400px;border: 1px solid #dddddd;border-radius: 5px;box-shadow: 5px 5px 20px #aaa;margin-left: auto;margin-right: auto;margin-top: 100px;padding: 20px 40px;}.account h2 {margin-top: 10px;text-align: center;}</style>
</head>
<body>
<div class="account"><h2>用户登录</h2><form method="post" novalidate>{% csrf_token %}<div class="form-group"><label>用户名</label>{{ form.username }}<span style="color: red;">{{ form.username.errors.0 }}</span></div><div class="form-group"><label>密码</label>{{ form.password }}<span style="color: red;">{{ form.password.errors.0 }}</span></div><div class="form-group"><label for="id_code">图片验证码</label><div class="row"><div class="col-xs-7">{{ form.code }}<span style="color: red;">{{ form.code.errors.0 }}</span></div><div class="col-xs-5"><img id="image_code" src="/image/code/" onclick="refreshImg(this)" style="width: 125px;" /></div></div></div><input type="submit" value="登 录" class="btn btn-primary"></form>
</div>
</body>
<script>function refreshImg(ths) {ths.src = '/image/code/?temp=' + Math.random();}
</script>
</html>

配置路由

path('login/', views.login),
path('image/code/', views.image_code),

4380bde6a2c44d15ba7cd469c8a4b05d.png

总结

  • 画图程序 check_code.py 保存在项目任意位置即可,只需在视图函数中导入即可。
  • Monaco.ttf 字体不可或缺,放置在静态文件中即可,但是需要修改 check_code.py 中的字体引入路径。
  • 验证用户输入的验证码是否正确,只需从 session 中取出生成的验证码与其比较即可。
  • 验证码刷新,只需让其再发送一次 get 请求即可。

自动生成验证码

1.安装 django-simple-captcha模块

pip install django-simple-captcha

2.注册到django容器

在 settings.py添加以下内容

INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','ums.apps.UmsConfig','captcha',
]

更新数据库表,

3.添加路由

在 urls.py 中添加 captcha 对应的路由

from django.contrib import admin
from django.urls import path, includeurlpatterns = [path('admin/', admin.site.urls),path('captcha', include('captcha.urls')),        # 验证码
]

4.修改Form表单

Django 中通常都是由 Form 生成表单,而验证码一般也伴随注册登录表单,因此需要在 forms.py 中添加验证码的字段。

from django import forms
from captcha.fields import CaptchaField     # 一定要导入这行class UserForm(forms.Form):username = forms.CharField(label='用户名',                # 在表单里表现为 label 标签max_length=128,widget=forms.TextInput(attrs={'class': 'form-control'})   # 添加 css 属性)captcha = CaptchaField(label='验证码',required=True,error_messages={'required': '验证码不能为空'})

5.编写视图函数

from django.shortcuts import render
from app.forms import UserFormdef index(request):register_form = UserForm(request.POST)if register_form.is_valid():passregister_form = UserForm()return render(request, 'index.html', {'register_form': register_form})

6.编写模板 

<html><head></head><body><form action='#' method='post'>{{ register_form.captcha.label_tag }}{{ register_form.captcha }} {{ </form></body>
</html>

总结

使用django-simple-captcha第三方库会生成验证码并存储到自带的captcha表中。

滑动验证码

官方下载源码包,并安装 geetest 模块​​​​​​

geetest-Getting started

gt3-python-sdk 文件。

pip install geetest
pip install requests    # 有可能还需要 requests 模块<!-- 引入封装了failback的接口--initGeetest -->
<script src="http://static.geetest.com/static/tools/gt.js"></script>

编写模板template

login.html

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>登录</title><link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.css' %}"><style>.login-col {margin-top: 100px;}</style>
</head>
<body>
<div class="container"><div class="row"><div class="well col-md-6 col-md-offset-3 login-col"><h3 class="text-center">登录</h3><form>{% csrf_token %}<div class="form-group"><label for="username">用户名:</label><input type="text" class="form-control" id="username" placeholder="用户名" name="username"></div><div class="form-group"><label for="password">密码:</label><input type="password" class="form-control" id="password" placeholder="密码" name="password"></div><!--极验科技滑动验证码--><div class="form-group"><!-- 放置极验的滑动验证码 --><div id="popup-captcha"></div></div><!--记住我--><div class="checkbox"><label><input type="checkbox"> 记住我</label></div><!--登录按钮--><button type="button" class="btn btn-primary btn-block" id="login-button">提交</button><!--错误信息--><span class="login-error"></span></form></div></div>
</div>
</body>
</html>

JS 代码主要分为两部分,

第一部分是获取表单的 value 值,向后台发送 Ajax 请求,以验证用户名及密码是否正确,若有错误将错误信息显示出来。

第二部分向后台获取验证码所需相关参数。 

<script src="{% static 'js/jquery-3.3.1.js' %}"></script>
<script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.js' %}"></script>
<!-- 引入封装了failback的接口--initGeetest -->
<script src="http://static.geetest.com/static/tools/gt.js"></script><script>var handlerPopup = function (captchaObj) {// 成功的回调captchaObj.onSuccess(function () {var validate = captchaObj.getValidate();var username = $('#username').val();var password = $('#password').val();console.log(username, password);$.ajax({url: "/accounts/login2/", // 进行二次验证type: "post",dataType: 'json',data: {username: username,password: password,csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),geetest_challenge: validate.geetest_challenge,geetest_validate: validate.geetest_validate,geetest_seccode: validate.geetest_seccode},success: function (data) {console.log(data);if (data.status) {// 有错误,在页面上显示$('.login-error').text(data.msg);} else {// 登录成功location.href = data.msg;}}});});// 当点击登录按钮时,弹出滑动验证码窗口$("#login-button").click(function () {captchaObj.show();});// 将验证码加到id为captcha的元素里captchaObj.appendTo("#popup-captcha");// 更多接口参考:http://www.geetest.com/install/sections/idx-client-sdk.html};$('#username, #password').focus(function () {// 将之前的错误清空$('.login-error').text('');});// 验证开始需要向网站主后台获取id,challenge,success(是否启用failback)$.ajax({url: "/accounts/pc-geetest/register?t=" + (new Date()).getTime(), // 加随机数防止缓存type: "get",dataType: "json",success: function (data) {// 使用initGeetest接口// 参数1:配置参数// 参数2:回调,回调的第一个参数验证码对象,之后可以使用它做appendTo之类的事件initGeetest({gt: data.gt,challenge: data.challenge,product: "popup", // 产品形式,包括:float,embed,popup。注意只对PC版验证码有效offline: !data.success // 表示用户后台检测极验服务器是否宕机,一般不需要关注// 更多配置参数请参见:http://www.geetest.com/install/sections/idx-client-sdk.html#config

视图函数 views.py

from django.shortcuts import render, redirect, HttpResponse
from django.http import JsonResponse
from geetest import GeetestLibdef login2(request):if request.method == 'POST':ret = {'status': False, 'msg': None}username = request.POST.get('username')password = request.POST.get('password')print(username, password)# 获取极验,滑动验证码相关参数gt = GeetestLib(pc_geetest_id, pc_geetest_key)challenge = request.POST.get(gt.FN_CHALLENGE, '')validate = request.POST.get(gt.FN_VALIDATE, '')seccode = request.POST.get(gt.FN_SECCODE, '')status = request.session[gt.GT_STATUS_SESSION_KEY]user_id = request.session["user_id"]print(gt, challenge, validate, seccode, status)if status:result = gt.success_validate(challenge, validate, seccode, user_id)else:result = gt.failback_validate(challenge, validate, seccode)if result:# 验证码正确# 利用auth模块做用户名和密码的校验user_obj = auth.authenticate(username=username, password=password)if user_obj:# 用户名密码正确# 给用户做登录auth.login(request, user_obj)ret["msg"] = "/accounts/home/"# return redirect('accounts:home')else:# 用户名密码错误ret["status"] = Trueret["msg"] = "用户名或密码错误!"else:ret["status"] = Trueret["msg"] = "验证码错误"return JsonResponse(ret)return render(request, "accounts/login2.html")# 请在官网申请ID使用,示例ID不可使用
pc_geetest_id = "b46d1900d0a894591916ea94ea91bd2c"
pc_geetest_key = "36fc3fe98530eea08dfc6ce76e3d24c4"# 处理极验 获取验证码的视图
def get_geetest(request):user_id = 'test'gt = GeetestLib(pc_geetest_id, pc_geetest_key)status = gt.pre_process(user_id)request.session[gt.GT_STATUS_SESSION_KEY] = statusrequest.session["user_id"] = user_idresponse_str = gt.get_response_str()return HttpResponse(response_str)

配置路由

from django.urls import path
from accounts import viewsapp_name = 'accounts'
urlpatterns = [path('home/', views.home, name='home'),# 极验滑动验证码 获取验证码的urlpath('pc-geetest/register/', views.get_geetest, name='get_geetest'),path('login2/', views.login2, name='login2'),
]

0ef2e2dae3264248a83fa1b5b2b712dd.png

总结

  • 画图程序 check_code.py 保存在项目任意位置即可,只需在视图函数中导入即可。
  • Monaco.ttf 字体不可或缺,放置在静态文件中即可,但是需要修改 check_code.py 中的字体引入路径。
  • 验证用户输入的验证码是否正确,只需从 session 中取出生成的验证码与其比较即可。
  • 验证码刷新,只需让其再发送一次 get 请求即可。

需要源代码评论区可以给我留言!

如果本文对你有帮助,记得点赞关注,你的支持是我最大的动力!

相关文章:

Django教程第4章 | Web开发实战-三种验证码实现

系列&#xff1a;Django学习教程 验证码的存在是为了防止系统被暴力破解攻击&#xff0c;几乎每个系统都有验证码。下面将介绍三种生成验证码方式。 您可以根据你自己的需要进行学习。 手动生成验证码 安装绘图依赖&#xff0c;利用的是画图模块 PIL 以及随机模块 random 在后…...

深度探讨 Golang 中并发发送 HTTP 请求的最佳技术

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 在 Golang 领域&#xff0c;并发发送 HTTP 请求…...

VUE指令(二)

vue会根据不同的指令&#xff0c;针对不同的标签实现不同的功能。指令是带有 v- 前缀的特殊标签属性。指令的职责是&#xff0c;当表达式的值改变时&#xff0c;将其产生的连带影响&#xff0c;响应式地作用于 DOM。 8、v-for&#xff1a;基于数据循环&#xff0c;多次渲染整个…...

开源对象存储服务器MinIO本地部署并结合内网穿透实现远程访问管理界面

文章目录 前言1. Docker 部署MinIO2. 本地访问MinIO3. Linux安装Cpolar4. 配置MinIO公网地址5. 远程访问MinIO管理界面6. 固定MinIO公网地址 前言 MinIO是一个开源的对象存储服务器&#xff0c;可以在各种环境中运行&#xff0c;例如本地、Docker容器、Kubernetes集群等。它兼…...

【TypeScript】tsconfig.json文件到底是干啥的?作用是什么?

参考学习博文&#xff1a; 掌握tsconfig.json 一、tsconfig.json简介 1、tsconfig.json是什么&#xff1f; TypeScript 使用 tsconfig.json 文件作为其配置文件&#xff0c;当一个目录中存在 tsconfig.json 文件&#xff0c;则认为该目录为 TypeScript 项目的根目录。 通常…...

wagtail的数据模型和渲染

文章目录 前言页面数据模型数据库字段部分搜索部分编辑面板基础面板结构化面板父页面/子页面类型规则页面URLs自定义页面模型的URL模式获取页面实例的URL 模板渲染为页面模型添加模板模板上下文自定义模板上下文更改模板动态选择模板Ajax 模板 内联模型在多个页面类型之间重用内…...

OpenHarmony4.0适配LVDS屏幕驱动

1.概述 手头有一块RK3568的开发板OK3568-C&#xff0c;但是还没有适配OpenHarmony&#xff0c;用的还是LVDS屏幕&#xff0c;但是官方和网上好像还没有OpenHarmony4.0的LVDS屏幕驱动的通用实现&#xff0c;所以决定尝试了一下适配该开发板&#xff0c;完成LVDS屏幕驱动的适配&…...

【playwright】新一代自动化测试神器playwright+python系列课程01-playwright驱动浏览器

Playwright驱动浏览器 安装 Playwright 时&#xff0c;Playwright默认自动安装了三种浏览器&#xff08;Chromium、Firefox 和 WebKit&#xff09;。我们可以驱动这三种浏览器中的任意一种。 使用with上下文管理器 启动chromium浏览器 python # # author: 测试-老姜 交流…...

POSIX API与网络协议栈

本文介绍linux中与tcp网络通信相关的POSIX API&#xff0c;在每次调用的时候&#xff0c;网络协议栈会进行的操作与记录。 POSIX API Posix API&#xff0c;提供了统一的接口&#xff0c;使程序能得以在不同的系统上运行。简单来说不同的操作系统进行同一个活动&#xff0c;比…...

互联网加竞赛 基于卷积神经网络的乳腺癌分类 深度学习 医学图像

文章目录 1 前言2 前言3 数据集3.1 良性样本3.2 病变样本 4 开发环境5 代码实现5.1 实现流程5.2 部分代码实现5.2.1 导入库5.2.2 图像加载5.2.3 标记5.2.4 分组5.2.5 构建模型训练 6 分析指标6.1 精度&#xff0c;召回率和F1度量6.2 混淆矩阵 7 结果和结论8 最后 1 前言 &…...

腾讯云 IPv6 解决方案

产品矩阵全覆盖 腾讯云全线产品 All in IPv6&#xff1b;云服务器、私有网络、负载均衡、内容分发、域名解析、DDoS 高防等都已支持 IPv6。 全球 IPv6 基础设施 腾讯云在全球开放25个地理区域&#xff0c;运营53个可用区&#xff1b;目前已有多个地域提供 IPv6 接入能力。 …...

Appium 自动化测试

1.Appium介绍 1&#xff0c;appium是开源的移动端自动化测试框架&#xff1b; 2&#xff0c;appium可以测试原生的、混合的、以及移动端的web项目&#xff1b; 3&#xff0c;appium可以测试ios&#xff0c;android应用&#xff08;当然了&#xff0c;还有firefoxos&#xff09;…...

深入浅出Android dmabuf_dump工具

目录 dmabuf是什么&#xff1f; dmabuf_dump工具介绍(基于Android 14) Android.bp dmabuf_dump.cpp 整体架构结构如下 dmabuf_dump主要包含以下功能 前置背景知识 fdinfo 思考 bufinfo Dump整个手机系统的dmabuf Dump某个进程的dmabuf​​​​​​​ 以Table[buff…...

Guava RateLimiter预热模型

本文已收录至我的个人网站&#xff1a;程序员波特&#xff0c;主要记录Java相关技术系列教程&#xff0c;共享电子书、Java学习路线、视频教程、简历模板和面试题等学习资源&#xff0c;让想要学习的你&#xff0c;不再迷茫。 什么是流量预热 我们都知道在做运动之前先得来几组…...

【搭建个人知识库-3】

搭建个人知识库-3 1 大模型开发范式1.1 RAG原理1.2 LangChain框架1.3 构建向量数据库1.4 构建知识库助手1.5 Web Demo部署 2 动手实践2.1 环境配置2.2 知识库搭建2.2.1 数据收集2.2.2 加载数据2.2.3 构建向量数据库 2.3 InternLM接入LangChain2.4 构建检索问答链1 加载向量数据…...

如何看待 Linux 内核邮件列表重启将内核中的 C 代码转换为 C++

如何看待 Linux 内核邮件列表重启将内核中的 C 代码转换为 C 的讨论&#xff1f; 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「Linux的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿…...

springboot网关添加swagger

添加依赖 <dependency><groupId>com.spring4all</groupId><artifactId>swagger-spring-boot-starter</artifactId><version>2.0.2</version></dependency>添加配置类&#xff0c;与服务启动类同一个层级 地址&#xff1a;http…...

代码随想录 Leetcode383. 赎金信

题目&#xff1a; 代码&#xff08;首刷自解 2024年1月15日&#xff09;&#xff1a; class Solution { public:bool canConstruct(string ransomNote, string magazine) {vector<int> v(26);for(auto letter : magazine) {v[letter - a];}for(auto letter : ransomNote…...

上下左右视频转场模板PR项目工程文件 Vol. 05

pr转场模板&#xff0c;视频画面上下左右转场后带有一点点回弹效果的PR项目工程模板 Vol. 05 项目特点&#xff1a; 回弹效果视频转场&#xff1b; Premiere Pro 2020及以上&#xff1b; 适用于照片和视频转场&#xff1b; 适用于任何FPS和分辨率&#xff1b; 视频教程。 PR转场…...

【正点原子STM32连载】第三十三章 单通道ADC采集实验 摘自【正点原子】APM32E103最小系统板使用指南

1&#xff09;实验平台&#xff1a;正点原子APM32E103最小系统板 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/docs/boards/xiaoxitongban 第三…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

2025季度云服务器排行榜

在全球云服务器市场&#xff0c;各厂商的排名和地位并非一成不变&#xff0c;而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势&#xff0c;对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析&#xff1a; 一、全球“三巨头”…...

快刀集(1): 一刀斩断视频片头广告

一刀流&#xff1a;用一个简单脚本&#xff0c;秒杀视频片头广告&#xff0c;还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农&#xff0c;平时写代码之余看看电影、补补片&#xff0c;是再正常不过的事。 电影嘛&#xff0c;要沉浸&#xff0c;…...

ui框架-文件列表展示

ui框架-文件列表展示 介绍 UI框架的文件列表展示组件&#xff0c;可以展示文件夹&#xff0c;支持列表展示和图标展示模式。组件提供了丰富的功能和可配置选项&#xff0c;适用于文件管理、文件上传等场景。 功能特性 支持列表模式和网格模式的切换展示支持文件和文件夹的层…...

【若依】框架项目部署笔记

参考【SpringBoot】【Vue】项目部署_no main manifest attribute, in springboot-0.0.1-sn-CSDN博客 多一个redis安装 准备工作&#xff1a; 压缩包下载&#xff1a;http://download.redis.io/releases 1. 上传压缩包&#xff0c;并进入压缩包所在目录&#xff0c;解压到目标…...