从零手写实现 nginx-23-nginx 对于 cookie 的操作
前言
大家好,我是老马。很高兴遇到你。
我们为 java 开发者实现了 java 版本的 nginx
https://github.com/houbb/nginx4j
如果你想知道 servlet 如何处理的,可以参考我的另一个项目:
手写从零实现简易版 tomcat minicat
手写 nginx 系列
如果你对 nginx 原理感兴趣,可以阅读:
从零手写实现 nginx-01-为什么不能有 java 版本的 nginx?
从零手写实现 nginx-02-nginx 的核心能力
从零手写实现 nginx-03-nginx 基于 Netty 实现
从零手写实现 nginx-04-基于 netty http 出入参优化处理
从零手写实现 nginx-05-MIME类型(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展类型)
从零手写实现 nginx-06-文件夹自动索引
从零手写实现 nginx-07-大文件下载
从零手写实现 nginx-08-范围查询
从零手写实现 nginx-09-文件压缩
从零手写实现 nginx-10-sendfile 零拷贝
从零手写实现 nginx-11-file+range 合并
从零手写实现 nginx-12-keep-alive 连接复用
从零手写实现 nginx-13-nginx.conf 配置文件介绍
从零手写实现 nginx-14-nginx.conf 和 hocon 格式有关系吗?
从零手写实现 nginx-15-nginx.conf 如何通过 java 解析处理?
从零手写实现 nginx-16-nginx 支持配置多个 server
从零手写实现 nginx-17-nginx 默认配置优化
从零手写实现 nginx-18-nginx 请求头+响应头操作
从零手写实现 nginx-19-nginx cors
从零手写实现 nginx-20-nginx 占位符 placeholder
从零手写实现 nginx-21-nginx modules 模块信息概览
从零手写实现 nginx-22-nginx modules 分模块加载优化
从零手写实现 nginx-23-nginx cookie 的操作处理
前言
大家好,我是老马。
这一节我们将配置的加载,拆分为不同的模块加载处理,便于后续拓展。
1. proxy_set_header Cookie 指令
介绍下 nginx proxy_set_header Cookie "admin_cookie=admin_value; $http_cookie"; 操作 cookie 的指令
在 Nginx 配置文件中,proxy_set_header
指令用于设置在代理请求中传递的 HTTP 头部字段。
通过 proxy_set_header
可以在将请求转发给上游服务器时添加、修改或删除请求头部字段。
具体来说,proxy_set_header Cookie "admin_cookie=admin_value; $http_cookie";
这条指令用于修改请求头中的 Cookie
字段。
它将一个新的 cookie(admin_cookie=admin_value
)添加到现有的请求 cookie 中。详细解释如下:
proxy_set_header
指令:这是 Nginx 用来设置请求头部字段的指令。Cookie
:这是要设置的头部字段名称。在这种情况下,设置的是 HTTP 请求的Cookie
头部。"admin_cookie=admin_value; $http_cookie"
:这是要设置的头部字段值。admin_cookie=admin_value
:这是要添加的新 cookie 值。admin_cookie
是 cookie 的名称,admin_value
是它的值。;
:分号用来分隔多个 cookie。$http_cookie
:这是一个 Nginx 的内置变量,它包含了当前请求中的所有 cookie 值。
通过这条指令,Nginx 会在转发请求到上游服务器之前,将一个新的 cookie 添加到现有的 cookie 中。这样上游服务器就会收到一个包含新添加的 admin_cookie=admin_value
的 Cookie
头部。
示例配置片段如下:
server {listen 80;server_name example.com;location / {proxy_pass http://backend_server;proxy_set_header Cookie "admin_cookie=admin_value; $http_cookie";}
}
在这个示例中,当客户端向 example.com
发起请求时,Nginx 会将请求转发给 backend_server
,并在请求头部的 Cookie
字段中添加一个新的 admin_cookie=admin_value
。
其他相关的 Nginx 指令
proxy_pass
:用于定义请求转发到的上游服务器。proxy_set_header
:用于设置转发请求的头部字段。
注意事项
- 安全性:在操作 cookie 时需要注意安全性,尤其是涉及敏感信息的 cookie。
- 兼容性:确保上游服务器能够正确处理添加的 cookie。
- 配置顺序:
proxy_set_header
通常放在location
或server
块中,并在proxy_pass
指令之前。
通过合理配置 proxy_set_header
指令,可以在 Nginx 中灵活地操作 HTTP 请求头部,满足各种代理需求。
netty 如何实现 对于 cookie 的新增/修改/删除?
这个我们原来就支持了
/*** # 增加或修改请求头* proxy_set_header X-Real-IP $remote_addr;* # 删除请求头* proxy_set_header X-Unwanted-Header "";** @param configParam 参数* @param context 上下文*/@Overridepublic void doBeforeDispatch(NginxCommonConfigParam configParam, NginxRequestDispatchContext context) {List<String> values = configParam.getValues();// $ 占位符号后续处理String headerName = values.get(0);String headerValue = values.get(1);FullHttpRequest fullHttpRequest = context.getRequest();// 设置HttpHeaders headers = fullHttpRequest.headers();if (StringUtil.isEmpty(headerValue)) {headers.remove(headerName);logger.info(">>>>>>>>>>>> doBeforeDispatch headers.remove({})", headerName);} else {// 是否包含if (headers.contains(headerName)) {headers.set(headerName, headerValue);logger.info(">>>>>>>>>>>> doBeforeDispatch headers.set({}, {});", headerName, headerValue);} else {headers.add(headerName, headerValue);logger.info(">>>>>>>>>>>> doBeforeDispatch headers.set({}, {});", headerName, headerValue);}}}
proxy_cookie_domain 指令
解释
proxy_cookie_domain
是 Nginx 的一个指令,用于修改代理服务器响应中的 Set-Cookie
头部的 Domain
属性。
这个指令通常用于在反向代理配置中,当上游服务器设置的 Domain
属性与客户端访问的域名不一致时,通过重写 Domain
属性来解决跨域问题。
语法
proxy_cookie_domain [上游服务器的域名] [要重写为的域名];
- 上游服务器的域名:指定要匹配并重写的
Domain
属性值。 - 要重写为的域名:指定新的
Domain
属性值。
默认值
proxy_cookie_domain off;
如果不设置 proxy_cookie_domain
,则默认不对 Set-Cookie
头部的 Domain
属性进行任何修改。
配置范围
该指令可以在 http
、server
或 location
块中配置。
示例
假设我们有一个后端服务器 backend.example.com
,它在设置 Cookie 时将 Domain
属性设为 backend.example.com
。
但是,客户端访问的是 www.example.com
。
我们可以使用 proxy_cookie_domain
来重写 Domain
属性,以便客户端能够正确地接收和发送这些 Cookie。
http {server {listen 80;server_name www.example.com;location / {proxy_pass http://backend.example.com;proxy_cookie_domain backend.example.com www.example.com;}}
}
在这个配置中,当上游服务器 backend.example.com
在响应中返回 Set-Cookie
头部时:
Set-Cookie: sessionid=abcd1234; Domain=backend.example.com; Path=/
Nginx 会将其重写为:
Set-Cookie: sessionid=abcd1234; Domain=www.example.com; Path=/
使用场景
- 跨域 Cookie 共享:当后端服务器和客户端使用不同的域名时,通过
proxy_cookie_domain
重写Set-Cookie
头部的Domain
属性,使 Cookie 能够在客户端域名下有效。 - 域名变更:如果网站的域名发生变化,通过该指令可以确保旧域名设置的 Cookie 仍然有效。
- 子域名问题:在使用子域名时,可以通过该指令将所有子域名的 Cookie 统一到主域名下。
注意事项
- 安全性:确保重写的域名是可信任的,以防止 Cookie 被不当共享。
- 精确匹配:
proxy_cookie_domain
的匹配是精确匹配的,因此需要确保指定的上游服务器域名与实际的Set-Cookie
头部中的Domain
属性完全一致。
通过合理使用 proxy_cookie_domain
指令,可以有效地解决跨域 Cookie 共享的问题,确保在反向代理场景下的 Cookie 设置和使用正确无误。
如何通过 netty,实现 proxy_cookie_domain 指令特性?
核心实现如下:
/*** 参数处理类 响应头处理** @since 0.20.0* @author 老马啸西风*/
public class NginxParamHandleProxyCookieDomain extends AbstractNginxParamLifecycleWrite {private static final Log logger = LogFactory.getLog(NginxParamHandleProxyCookieDomain.class);@Overridepublic void doBeforeWrite(NginxCommonConfigParam configParam, ChannelHandlerContext ctx, Object object, NginxRequestDispatchContext context) {if(!(object instanceof HttpResponse)) {return;}List<String> values = configParam.getValues();if(CollectionUtil.isEmpty(values) || values.size() < 2) {return;}// 原始String upstreamDomain = values.get(0);// 目标String targetDomain = values.get(1);HttpResponse response = (HttpResponse) object;HttpHeaders headers = response.headers();String setCookieHeader = headers.get(HttpHeaderNames.SET_COOKIE);if (setCookieHeader != null) {Set<Cookie> cookies = ServerCookieDecoder.STRICT.decode(setCookieHeader);Set<Cookie> modifiedCookies = cookies.stream().map(cookie -> {if (upstreamDomain.equals(cookie.domain())) {Cookie newCookie = new DefaultCookie(cookie.name(), cookie.value());newCookie.setDomain(targetDomain);newCookie.setPath(cookie.path());newCookie.setMaxAge(cookie.maxAge());newCookie.setSecure(cookie.isSecure());newCookie.setHttpOnly(cookie.isHttpOnly());return newCookie;}return cookie;}).collect(Collectors.toSet());List<String> encodedCookies = ServerCookieEncoder.STRICT.encode(modifiedCookies);headers.set(HttpHeaderNames.SET_COOKIE, encodedCookies);}logger.info(">>>>>>>>>>>> doBeforeWrite proxy_hide_header upstreamDomain={} => targetDomain={}", upstreamDomain, targetDomain);}@Overridepublic void doAfterWrite(NginxCommonConfigParam configParam, ChannelHandlerContext ctx, Object object, NginxRequestDispatchContext context) {}@Overrideprotected String getKey(NginxCommonConfigParam configParam, ChannelHandlerContext ctx, Object object, NginxRequestDispatchContext context) {return "proxy_hide_header";}}
proxy_cookie_flags 指令
支持哪些?
在 Nginx 中,proxy_cookie_flags
指令用于设置从代理服务器返回给客户端的 Set-Cookie
头中特定 cookie 的属性标志。主要支持的配置选项包括:
HttpOnly:将
HttpOnly
标志添加到 cookie,使得 JavaScript 无法通过document.cookie
访问该 cookie。proxy_cookie_flags <cookie_name> HttpOnly;
Secure:将
Secure
标志添加到 cookie,仅在通过 HTTPS 协议发送时才会发送该 cookie。proxy_cookie_flags <cookie_name> Secure;
SameSite:设置
SameSite
标志,限制浏览器仅在同站点请求时发送该 cookie,有助于防止跨站点请求伪造(CSRF)攻击。proxy_cookie_flags <cookie_name> SameSite=Strict;
支持的
SameSite
值包括Strict
、Lax
和None
。Max-Age:设置
Max-Age
属性,指定 cookie 的过期时间(秒)。通常用于设置持久化 cookie 的过期时间。proxy_cookie_flags <cookie_name> Max-Age=3600;
Expires:设置
Expires
属性,指定 cookie 的过期时间点。通常以 GMT 格式的日期字符串指定。proxy_cookie_flags <cookie_name> Expires=Wed, 21 Oct 2026 07:28:00 GMT;
Domain:设置
Domain
属性,指定可接受该 cookie 的域名范围。通过proxy_cookie_domain
指令更常用地配置。proxy_cookie_flags <cookie_name> Domain=example.com;
Path:设置
Path
属性,指定该 cookie 的路径范围。proxy_cookie_flags <cookie_name> Path=/;
示例
以下是一些示例,展示如何使用 proxy_cookie_flags
指令设置不同的 cookie 标志:
server {listen 80;server_name example.com;location / {# 添加 HttpOnly 和 Secure 标志proxy_cookie_flags session_cookie HttpOnly Secure;# 设置 SameSite 标志为 Strictproxy_cookie_flags mycookie SameSite=Strict;# 设置 Max-Age 为 1 小时proxy_cookie_flags persistent_cookie Max-Age=3600;# 设置 Expires 属性proxy_cookie_flags old_cookie Expires=Wed, 21 Oct 2026 07:28:00 GMT;# 设置 Domain 属性proxy_cookie_flags global_cookie Domain=example.com;# 设置 Path 属性proxy_cookie_flags local_cookie Path=/subpath;proxy_pass http://backend;}
}
通过这些配置,您可以灵活地控制从代理服务器返回的 Set-Cookie
头中各个 cookie 的属性,以满足安全需求和业务逻辑。
java 核心实现
public void doBeforeWrite(NginxCommonConfigParam configParam, ChannelHandlerContext ctx, Object object, NginxRequestDispatchContext context) {if(!(object instanceof HttpResponse)) {return;}List<String> values = configParam.getValues();if(CollectionUtil.isEmpty(values) || values.size() < 2) {return;}HttpResponse response = (HttpResponse) object;HttpHeaders headers = response.headers();String cookieHeader = headers.get(HttpHeaderNames.COOKIE);final String cookieName = values.get(0);if (cookieHeader != null) {Set<Cookie> cookies = ServerCookieDecoder.STRICT.decode(cookieHeader);Set<Cookie> modifiedCookies = cookies.stream().map(cookie -> {// 相同的名字if (cookieName.equals(cookie.name())) {// HttpOnly Securefor(int i = 1; i < values.size(); i++) {String value = values.get(i);if("HttpOnly".equals(value)) {cookie.setHttpOnly(true);}if("Secure".equals(value)) {cookie.setSecure(true);}// 拆分if(!value.contains("=")) {return cookie;}String[] items = value.split("=");String itemKey = items[0];String itemVal = items[1];// if("SameSite".equals(itemKey) && "Strict".equals(itemVal)) {
// }if("Max-Age".equals(itemKey)) {cookie.setMaxAge(Long.parseLong(itemVal));}if("Expires".equals(itemKey)) {Date expireDate = calcDate(itemVal);long maxAge = expireDate.getTime() - System.currentTimeMillis();cookie.setMaxAge(maxAge);}if("Domain".equals(itemKey)) {cookie.setDomain(itemVal);}if("Path".equals(itemKey)) {cookie.setPath(itemVal);}}}return cookie;}).collect(Collectors.toSet());List<String> encodedCookies = ServerCookieEncoder.STRICT.encode(modifiedCookies);headers.set(HttpHeaderNames.COOKIE, encodedCookies);}logger.info(">>>>>>>>>>>> doBeforeWrite proxy_cookie_flags values={}", values);}
nginx proxy_cookie_path 指令
介绍
在 Nginx 中,proxy_cookie_path
指令用于修改传递到后端服务器的 HTTP 请求中的 Cookie 的路径。
这个指令通常在反向代理服务器配置中使用,用于调整传递给后端服务器的 Cookie 的路径信息,以适应后端服务器的预期路径结构。
语法和用法
语法:
proxy_cookie_path regex path;
参数解释:
regex
:一个正则表达式,用于匹配要修改的 Cookie 的路径。path
:要替换成的路径。
示例
假设有如下配置:
location /app/ {proxy_pass http://backend.example.com;proxy_cookie_path ~*^/app(.*) $1;
}
在这个示例中:
proxy_cookie_path
指令配合proxy_pass
使用,表示将从客户端接收的带有路径/app/
的 Cookie 的路径信息去除/app
部分后再传递给后端服务器。
例如,如果客户端发送的 Cookie 路径是 /app/session
, Nginx 将修改为 /session
后传递给后端服务器。
注意事项
- 使用
proxy_cookie_path
时,确保理解你的后端服务器期望接收的 Cookie 路径格式,以便正确设置正则表达式和路径。 - 正则表达式必须能够正确匹配客户端发送的 Cookie 路径。
- 这个指令通常用于调整不同路径的代理请求,以便与后端服务器的预期路径结构匹配。
java 核心实现
public void doBeforeDispatch(NginxCommonConfigParam configParam, NginxRequestDispatchContext context) {List<String> values = configParam.getValues();if(CollectionUtil.isEmpty(values) || values.size() < 2) {throw new Nginx4jException("proxy_cookie_path 必须包含2个参数");}FullHttpRequest request = context.getRequest();// 原始String regex = values.get(0);String path = values.get(1);HttpHeaders headers = request.headers();String cookieHeader = headers.get(HttpHeaderNames.COOKIE);if (cookieHeader != null) {String modifiedCookieHeader = cookieHeader.replaceAll(regex, path);headers.set(HttpHeaderNames.COOKIE, modifiedCookieHeader);}logger.info(">>>>>>>>>>>> doBeforeDispatch proxy_cookie_path replace regex={} => path={}", regex, path);
}
小结
对于 cookie 的处理,让我们的请求可以更加强大灵活。
proxy_cookie_domain
: 设置后端服务器响应的 Cookie 中的域名。proxy_cookie_flags
: 设置后端服务器响应的 Cookie 的标志位。proxy_cookie_path
: 设置后端服务器响应的 Cookie 的路径。
我是老马,期待与你的下次重逢。
开源地址
为了便于大家学习,已经将 nginx 开源
https://github.com/houbb/nginx4j
相关文章:

从零手写实现 nginx-23-nginx 对于 cookie 的操作
前言 大家好,我是老马。很高兴遇到你。 我们为 java 开发者实现了 java 版本的 nginx https://github.com/houbb/nginx4j 如果你想知道 servlet 如何处理的,可以参考我的另一个项目: 手写从零实现简易版 tomcat minicat 手写 nginx 系列 …...

Python语言例题集(015)
#!/usr/bin/python3 #使用列表模仿队列的操作。 class Queue(): def init(self): self.queue[] def enqueue(self,data):self.queue.insert(0,data)def dequeue(self):if len(self.queue):return self.queue.pop()return "队列是空的"qQueue() q.enqueue(‘Grape’…...

Halcon C++ XLD 数据写入图片
1. xld转换为Region 生成与调用函数 gen_cross_contour_xld (CrossXld, Rows, UpdateCols, 6, 0) get_xld_region (CrossXld, xldRegions)函数实现 get_xld_region * 计算XLD个数 count_obj (BaseXld, Number) * 生成空的区域(结果) gen_empty_region…...

一文入门vim
先来波快问快答。 第一个问题,vim是什么? vim就是一文本编辑器。 第二个问题,我们为什么要使用vim? 好像在终端中可选择使用的文本编辑器也不多(其他有,但是相对而言vim用的比较广泛) 第三…...

植物ATAC-seq文献集锦(三)——果实发育篇
ATAC-seq在植物研究领域的应用我们已经介绍2期了,本期我们聚焦ATAC-seq技术在果实发育方向的应用案例。 植物ATAC-seq文献集锦(一)——基因组篇 植物ATAC-seq文献集锦(二)——生长发育篇 文献一:Ident…...

在自己的电脑上搭建我的世界Java版服务器
很多朋友,喜欢玩Minecraft,也希望搭建一个服务器,用于和小伙伴联机; 并且,拥有服务器后,即使所有玩家都下线,“世界”依旧在运行,玩家可以随时参与其中,说不定一上线&am…...

1.PyQt6库和工具库QTDesigner安装
1.安装PyQT6和pyqt6-tools 1. PyQt6库是PyQt的开发库 2.pyqt6-tool时QTDesigner设计器工具支持库 pip install PyQt6 pip install pyqt6-tools 2.在Pycharm中配置外部工具QTDesigner和PYGIC 配置外部工具QTDesigner 1. QTDesigner是QT界面设计器 2.打开Pycharm->Settin…...

Hbase搭建教程
Hbase搭建教程 期待您的关注 ☀小白的Hbase学习笔记 目录 Hbase搭建教程 1.上传hbase的jar包并解压 2.重新登录 3.启动zookeeper 4.配置环境变量 5.关闭ZK的默认配置 6.修改hbase-site.xml文件 7.修改regionservers文件 8.将配置好的文件分发给其它节点 9.配置环境变量…...

利用three-csg-ts对做物体交互式挖洞
默认物体均为居中,如果指定位置没有发生偏移,可能是因为在执行布尔操作之前没有正确设置变换。确保在进行布尔运算之前应用所有必要的变换。以下是经过修正的完整代码示例,它会确保圆柱正确旋转并与盒子进行 CSG 操作。 安装依赖 首先&…...

腾讯云对象存储不绑定自定义备案域名不给下载应该如何处理?
从2024年1月1日起,腾讯云对象存储(COS)将实施新政策:新创建的存储桶不再支持使用path-style域名(即存储桶绝对路径)。此外,使用默认域名访问的新存储桶将不再支持任意类型文件的预览,…...

C 语言实例 - 输出数组
使用 for 循环输出数组 #include <stdio.h>int main() {int array[10] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};int loop;for(loop 0; loop < 10; loop)printf("%d ", array[loop]);return 0; }输出结果为: 1 2 3 4 5 6 7 8 9 0使用 for 循环逆向输…...

回溯算法练习题(2024/6/10)
1组合 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1: 输入:n 4, k 2 输出: [[2,4],[3,4],[2,3],[1,2],[1,3],[1,4], ] 示例 2: 输入:n …...

机器学习--线性模型和非线性模型的区别?哪些模型是线性模型,哪些模型是非线性模型?
文章目录 引言线性模型和非线性模型的区别线性模型非线性模型 总结线性模型非线性模型 引言 在机器学习和统计学领域,模型的选择直接影响到预测的准确性和计算的效率。根据输入特征与输出变量之间关系的复杂程度,模型可以分为线性模型和非线性模型。线性…...

[linux] Qwen2Tokenizer报错 transformers版本问题
上午没问题,下午pull了新代码,就有了报错。。 发现是transformers版本问题。但。。其实我都默认安的是最新版本。。 也许这就是人生吧。。 报错: File "/Pai-Megatron-Patch/megatron_patch/tokenizer/__init__.py", line 213…...

算法刷题笔记 单链表(C++实现)
文章目录 题目描述基本思路实现代码 题目描述 实现一个单链表,链表初始为空,支持三种操作: 向链表头插入一个数;删除第 k个插入的数后面的一个数;在第 k个插入的数后插入一个数。 现在要对该链表进行M次操作&#x…...

Oracle 排查慢SQL
Oracle 排查慢SQL select * from v s q l a r e a w h e r e r o w n u m < 10 ; s e l e c t ∗ f r o m v sqlarea where rownum<10; select * from v sqlareawhererownum<10;select∗fromvsql where rownum<10; select * from dba_hist_sqltext where rownum<…...

java技术专家面试指南80问【java学习+面试宝典】(七)
Dubbo需要 Web 容器吗? 不需要,如果硬要用 Web 容器,只会增加复杂性,也浪费资源。 PrintStream、BufferedWriter、PrintWriter的比较? PrintStream类的输出功能非常强大,通常如果需要输出文本内容,都应…...

4机器学习期末复习
在机器学习中,数据清洗与转换包括哪些内容? 对数据进行初步的预处理,需要将其转换为一种适合机器学习模型的表示形式对许多模型类型来说,这种表示就是包含数值数据的向量或者矩阵: 1)将类别数据编码成为对…...

chatgpt: int t[] int *t 区别
在C语言中,int t[]和int *t虽然在某些情况下可以相互替换,但它们有一些关键的区别。这些区别主要体现在声明的语义、内存分配方式和使用场景上。以下是详细的解释: ### 1. int t[] #### 语义: - int t[]声明了一个数组,t是一个数…...

网络安全技术实验六 入侵检测技术实践
一、实验目的和要求 理解基于网络的入侵检测系统的基本原理,掌握snort IDS工作机理; 学习应用snort三种方式工作;熟练编写snort规则; 完成snort数据包记录、日志查看、字符串匹配、ARP欺骗攻击检测、端口扫描工具检测等功能。 …...

SpringBoot中获取当前请求的request和response
在Spring Boot中,你可以以多种方式获取当前请求的HttpServletRequest和HttpServletResponse对象。以下是几种常见的写法示例: 1. 在方法参数中声明 最常见和推荐的方式是在控制器方法的参数中直接声明HttpServletRequest和HttpServletResponse对象。Sp…...

Neo4j 桌面版打不开踩坑贴
真的踩坑。。。没有人告诉我为啥桌面版和社区版不能一起下啊!! 我是先下载了社区版之后再下载的桌面版,结果桌面版界面一直打不开。 尝试了网上多种办法都没效果,好多都是说jdk不兼容导致无法打开,让我从JDK 17 ->…...

[数据集][目标检测]中国象棋检测数据集VOC+YOLO格式300张12类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):300 标注数量(xml文件个数):300 标注数量(txt文件个数):300 标注类别…...

全方位·多层次·智能化,漫途水库大坝安全监测方案
党的十九届五中全会提出,到2025年前,完成新出现病险水库的除险加固,配套完善重点小型水库雨水情和安全监测设施,实现水库安全鉴定和除险加固常态化。 加快推进小型水库除险加固。加快构建气象卫星和测雨雷达、雨量站、水文站组成…...

windows安装SQLyog
windows安装SQLyog 1. 下载 SQLyog 安装包 访问 SQLyog 的官方网站。在网站上找到下载链接,通常会有一个“Download”或“Try Now”按钮。如果需要注册或填写信息以获取下载链接,请按提示操作。 2. 运行安装程序 下载完成后,双击运行下载…...

jEasyUI 转换 HTML 表格为数据网格
jEasyUI 转换 HTML 表格为数据网格 jEasyUI 是一个基于 jQuery 的框架,它为用户提供了一套完整的用户界面组件,使得网页开发变得更加简单快捷。在本文中,我们将探讨如何使用 jEasyUI 将一个普通的 HTML 表格转换为功能丰富的数据网格(datagrid)。 为什么使用数据网格? …...

深度解析RocketMq源码-持久化组件(一) MappedFile
1. 绪论 rocketmq之所以能够有如此大的吞吐量,离不开两个组件,一个是利用netty实现的高性能网络通信组件;另一个就是利用mmap技术实现的存储组件。而在rocketmq的存储组件中主要有三个组件,分别是持久化文件commitLog,…...

贝壳APP渗透测试WP
前期配置 环境说明 使用PIXEL 4手机,为Android 12系统 APP名为贝壳找房,包名com.lianjia.beike,版本号3.01.10,截至2024/05/07为最新版,小米应用市场下载 绕过反Frida机制 可以参考往期推送,《绕过最新…...

IDEA快速入门02-快速入门
二、快速入门 2.1 打开IDEA,点击New一个项目 入口,依次打开 File -> New -> Project。 2.2 使用Spring Initializr方式构建Spring Boot项目 2.3 设置项目所属组、项目名称、java版本等 2.4 选择SpringBoot版本及依赖组件 点击Create进行创建。 2.6 创建成…...

快速构建本地RAG聊天机器人:使用LangFlow和Ollama实现无代码开发
基于LangChain的快速RAG应用原型制作方法 还记得构建智能聊天机器人需要数月编码的日子吗? LangChain这样的框架确实简化了开发流程,但对非程序员来说,数百行代码仍然是一道门槛。 有没有更简单的方法呢? 图片由 Ravi Palwe 在…...