MoreRSS

site iconSunZhongWei | 孙仲维 修改

博客名「大象笔记」,全干程序员一名,曾在金山,DNSPod,腾讯云,常驻烟台。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

SunZhongWei | 孙仲维 的 RSS 预览

Cloudflare 设置了网站缓存规则,但是依旧返回 pragma no-cache HTTP 头

2026-08-12 20:39:49

例如在 Cloudflare 的页面缓存规则中,设置了 3 天,但是返回的网页 HTTP 头是:

Cloudflare 页面返回

  • age 73132
  • alt-svc h3=“:443”; ma=86400
  • cache-control max-age=7200
  • cf-cache-status HIT
  • cf-ray a29e93ee2b8ca094-FRA
  • content-type text/html; charset=utf-8
  • date Wed, 12 Aug 2026 09:50:48 GMT
  • expect-ct max-age=86400, enforce
  • expires Wed, 17 Aug 2005 00:00:00 GMT
  • last-modified Tue, 11 Aug 2026 13:14:29 GMT
  • pragma no-cache

pragma no-cache 代表什么

pragma: no-cache 代表这是一个 HTTP/1.0 协议的遗留指令,其作用是要求缓存服务器在返回内容前,必须向源服务器进行验证(即强制回源验证)。

但在当前的场景中,它基本不起作用,可以忽略。因为现代浏览器和 Cloudflare 优先遵循 HTTP/1.1 的 Cache-Control 头。

现代标准以 Cache-Control 为准。如果同时存在,客户端会忽略 Pragma。

3 天 VS 2 小时

cache-control: max-age=7200(源站要求缓存 2 小时)

age: 73132(当前资源已在 Cloudflare 缓存中存了 73132 秒 ≈ 20.3 小时)

age 远大于 max-age,这证明了 Cloudflare 的“边缘缓存 TTL”(设置的 3 天/259200 秒)成功覆盖(覆盖/忽略)了源站的 max-age=7200。缓存规则已经完全生效,Cloudflare 强制将这个页面保留了将近一天,并且还会继续保留到 3 天期满。

Joomla 配置

pragma: no-cache 常由 Joomla 的系统缓存设置产生。关闭它可能从源头解决问题。

  • 登录 Joomla 管理员后台。
  • 进入 系统 (System) -> 全局配置 (Global Configuration)。
  • 点击 系统 (System) 选项卡。
  • 将 系统缓存 (System Cache) 设置为 “关闭 - 不缓存” (OFF - Don’t cache)。
  • 保存设置并清除 Joomla 缓存。

Joomla 修改源码

如果没有权限修改 Joomla 后台配置,可以在服务器上直接修改源码:

libraries/vendor/joomla/application/src/AbstractWebApplication.php

搜索 no-cache 并注释掉:

 if (!$this->allowCache()) {
    // Expires in the past.
    $this->setHeader('Expires', 'Wed, 17 Aug 2005 00:00:00 GMT', true);

    // Always modified.
    $this->setHeader('Last-Modified', \gmdate('D, d M Y H:i:s') . ' GMT', true);
    $this->setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0', false);

    // HTTP 1.0
    $this->setHeader('Pragma', 'no-cache');
}

2026 Joomla SP Page Builder 漏洞, 允许未授权用户上传恶意 PHP 代码

2026-08-11 21:49:20

又中招了,GTranslate 服务说网站请求量过大,停止了服务。查看首页,发现一个首页,加载了 1000 多个 css 文件。

发现是 Joomla SP Page Builder 的漏洞,会通过 POST 上传一堆文件。

SP Page Builder在2026年被曝出多个严重安全漏洞(如CVE-2026-48908、CVE-2026-66494等),允许未授权用户上传恶意文件甚至执行代码

然后影响首页加载很多 css 文件。好在,之前添加了 nginx 规则,会阻止 media 路径下的所有代码执行。所以,只会看到加载了一千多个 css 文件,但是没有其他影响。

晚上,清理了这些配置,并且增加了 cloudflare 规则,阻止了 SP Page Builder 相关的 post 请求。

Nginx 日志

POST /index.php?option=com_sppagebuilder&task=asset.uploadCustomIcon 200

GET /media/com_sppagebuilder/assets/iconfont/icorlycgq/fonts/fawvfmj.PHP?t=ixbszjbawvencrtq&c=echo+SPPB-RCE-%24%28%287%2A6%29%29 HTTP/1.1 403 

攻击 IP 来自新加坡的 194.233.86.244。上传完成后,就开始尝试执行恶意 PHP 代码,好在我阻止了 media 下的 PHP 代码执行。

cloudflare 拦截规则

当请求是 POST 时,并且

http.request.uri.query contains "option=com_sppagebuilder"

就直接拦截。不用 Nginx 拦截的原因是,我不知道怎么设置 nginx 判断这种多条件的情况。而且用 cloudflare 也更节省服务器资源。

测试

确认是否禁止了 com_sppagebuilder 相关的 POST 请求。

curl -X POST "http://your-domain.com/index.php?option=com_sppagebuilder&task=asset.uploadCustomIcon" -I

如果返回 HTTP/2 403,说明拦截成功了。

清理首页加载项

即便清空了服务器 /media/com_sppagebuilder/assets/iconfont/ 下的恶意文件目录。首页依然会加载一堆 css,虽然报 404 也非常讨厌。

需要到数据库的 xxx_sppagebuilder_assets 数据表,清理掉里面的恶意文件配置。

枯燥的工作需要 SKILL 调剂,Spring Boot 中 Mybatis SQL 单元测试 SKILL

2026-08-10 19:59:07

枯燥的 MES 重构工作,感觉没有尽头,调教 SKILL 反而成了唯一的乐趣。

背景

Spring Boot 功能代码开发完成后,可以让 AI 自动编译,通过编译日志来排查是否有问题,然后自动修复。
但是,对于 Mybatis XML 文件中的 SQL 代码,在编译时通常排查不出问题,只有执行时才能发现数据库报错。例如:

Error querying database. Cause: java.sql.SQLSyntaxErrorException: ORA-01722: 无效数字

或者

Error querying database. Cause: java.sql.SQLDataException: ORA-01861: 文字与格式字符串不匹配

这些都是 AI 在实现代码时,经常会制造的一些 bug。虽然根源是没有把数据库表结构喂给 AI。

但是,我依然想实现一个 Skill 能自动发现 Mybatis XML 文件中的 SQL 代码的问题,然后自动修复,省去了我来回在界面里点击,再把错误信息复制给 AI,如此反复的过程。

需求

这个 Skill 可以对指定功能的 mybatis xml 文件中的 SQL 做单元测试。

H2 数据库还是 Oracle 数据库

如果要模拟数据库操作,是使用 H2 数据库(内存数据库,支持各种数据库的 SQL)还是 Oracle 数据库呢?

因为 SQL 强依赖 Oracle 专有语法(DECODE/TO_DATE)和真实表数据,只有连真实库才能真正验证。最后还是决定使用测试环境的 Oracle 数据库。

create skill prompt

这个 skill 接收功能名称,判断指定功能是否已经有代码实现了,如已实现,则自动创建对应的 mybatis xml 相关的 SQL 测试案例。如果已经有了单元测试,则按照该 skill 的最新标准修正单元测试。

需要通过 python (oracledb 库)脚本连接测试数据库(jdbc:oracle:thin:@//x.x.x.x:1521/testdb),来判断相关表的表结构、字段类型。并插入测试数据,注意,只能使用测试数据库执行。绝对不可以连接正式生产数据库来执行上面的操作。

同时把对应的表结构整理到 docs\database\tables.md 中, 使用 markdown 格式,二级标题是表名及对应的中文名,内容是表结构或者建表语句的 code block。目的是方便后续开发,或者调试 bug 时可以参考。

写入的测试数据,不需要清理,因为测试数据库是独立的,不会影响生产环境。

然后执行测试,如果测试通过,则提示测试通过,否则提示测试失败,并输出失败的测试案例名称。

测试需要覆盖到各种前端查询条件的场景,即,各种前端查询条件的场景,需要写一个测试案例,测试案例名称是功能名称 + 前端查询条件的名称。

测试流程

  • 先实现一个单元测试示例。确定方案选型
  • 实现第一版自动化测试 skill
  • 基于 skill 完善之前实现的单元测试示例

意外惊喜

AI 在编写 Skill 时,实际运行试点测试时,测试基础设施精确复现了你之前报告的 ORA-01861 错误——测试库有数据时 sn.created_at >= TO_DATE(?, ‘yyyy-MM-dd hh24:mi:ss’)(created_at 是 VARCHAR2)抛”文字与格式字符串不匹配”。这正验证了本 skill 的核心价值:真实测试库 + 有数据的表才能暴露空表单测发现不了的 SQL 问题。测试失败案例名为 queryByTimeRange。根因与修复已在 CODEBUDDY.md 记录(去掉 TO_DATE 改字符串比较)。

需要能自动修复

由于 plan 约束”不得改动业务源码”,我没有擅自修改 XML。需要我修复这个业务 XML 的 TO_DATE bug 吗? 修复后时间条件测试即可通过,年周号自检记录 在真实库的时间查询功能也将恢复正常。

修改 skill 的规则,如果发现测试失败,则自动修复,允许改动业务源码。

只运行单个测试类

mvn -pl ruoyi-admin test "-Dtest=SomeFunctionMapperTest" "-Dskip.tests=false"

运行某个包下的所有测试

mvn -pl ruoyi-admin test "-Dtest=com.sunzhongwei.somefunction.*" "-Dskip.tests=false"

运行所有 Mapper 测试

mvn -pl ruoyi-admin test "-Dtest=*MapperTest" "-Dskip.tests=false"

为何没有使用 MyBatis-Spring-Boot-Starter-Test

https://mybatis.org/spring-boot-starter/mybatis-spring-boot-test-autoconfigure/zh_CN/index.html

开发环境的版本: mybatis-plus-boot-starter 3.5.1

1. 项目用了 Dynamic Datasource(多数据源)

当前 RuoYi 项目生产配置用的是 dynamic-datasource-spring-boot-starter@DS 注解切数据源)。@MybatisTest 的自动配置期望的是单一 spring.datasource.* 数据源 + 默认的 SqlSessionFactory。而 dynamic-datasource 会自定义 DataSource 代理和 SqlSessionFactory,两者容易互相干扰——这也是为什么之前手工方案里特意用 DriverManagerDataSource 绕开 Druid/dynamic-datasource。

2. MyBatis-Plus 的全局配置兼容性

项目用的是 MyBatis-Plusmybatis-plus-boot-starter),而 mybatis-spring-boot-starter-test@MybatisTest 自动配置是基于原生 MyBatisSqlSessionFactory 来探测和加载的。官方 starter 对 MP 的兼容不是开箱即用,需要额外配置(如指定 MybatisSqlSessionFactoryBean、全局 MybatisConfiguration 等)。当前方案用的 MybatisSqlSessionFactoryBean + setTypeAliasesPackage 正是为了兼容 MP。

3. 类型别名(SysConfig 等)需要手工指定

@MybatisTest 默认不扫描 MP 的 typeAliasesPackage,之前我们踩过 SysConfig 别名解析失败的坑,手工配置里通过 setTypeAliasesPackage("com.sunzhongwei.domain") 明确解决了。

小米手机桌面小部件调试,始终看不到桌面组件

2026-08-09 22:05:35

周末晚上开发了一款自用的 Android 桌面组件,但是调试时,始终看不到桌面组件。在系统里,支持小部件应用的列表里,也看不到这个应用名称。我以为是代码的 bug,让 AI 改了好几遍,也没搞定。最后还是用 DeepSeek 网页版问了出来。

小米小部件 vs 安卓原生组件

小米系统将小部件分为“小米小部件”和“安卓原生组件”两类,它们共享同一个池子。

  • 如果你按照小米小部件规范开发,它会出现在“小部件中心”;
  • 若遵循标准Android开发,则需在原生组件入口寻找。而这个入口是被弱化的

如何找到你的组件:在桌面上双指捏合或从负一屏点击“+”号,进入“小部件中心”。如果这里没有,可以尝试长按桌面空白处,选择“添加工具”或“小部件”,点击右上角的搜索按钮,然后在应用列表或底部寻找“安卓小部件”分类。

github 小部件

怪不得,我觉得小部件中心里支持小部件的应用好少,原来是被偷偷藏了起来。我甚至在里面找到了 github 的桌面小组件。国产 Android 魔改系统不知道在发什么疯?

Android Studio Quail 3 | 2026.1.3 国内源配置

2026-08-09 19:54:27

今天升级到了 Android Studio Quail 3 | 2026.1.3。发现还是要重新配置一遍国内源。

新建一个 Jetpack Compose Koltin 项目。

Could not install Gradle Read timed out

打开文件:gradle\wrapper\gradle-wrapper.properties

替换 services.gradle.org 源为腾讯云镜像:

#distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-9.5.0-bin.zip

参考:

React Native 编译 Android APK

依赖包的国内镜像

settings.gradle.kts

pluginManagement {
    repositories {
        google {
            content {
                includeGroupByRegex("com\\.android.*")
                includeGroupByRegex("com\\.google.*")
                includeGroupByRegex("androidx.*")
            }
        }

        maven("https://maven.aliyun.com/repository/public") // 阿里云镜像
        maven("https://maven.aliyun.com/repository/central") // Central 仓库镜像
        maven("https://maven.aliyun.com/repository/gradle-plugin") // Gradle 插件镜

        mavenCentral()
        gradlePluginPortal()
    }
}
plugins {
    id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        maven("https://maven.aliyun.com/repository/public")
        maven("https://maven.aliyun.com/repository/central")
        google()
        mavenCentral()
    }
}

rootProject.name = "大象笔记 APP"
include(":app")

参考:

新版本 Android Studio settings.gradle 中切换国内源

Windows PowerShell 中安装 NeoVim

2026-08-01 17:32:59

我发现在 Windows PowerShell 中使用 NeoVim 非常流畅,跟 linux 中没有两样,看来每台 windows 上都应该安装一份 neovim 了。所以记录一下配置。

安装

winget install Neovim.Neovim

查看版本号

> nvim --version
NVIM v0.12.4
Build type: Release
LuaJIT 2.1.1774638290

说明安装成功了。

设置别名

用 nvim 命令还是别扭,需要设置一个 vim 别名。

查看 PowerShell 的配置文件路径:

> echo $PROFILE
C:\Users\zhong\Documents\PowerShell\Microsoft.PowerShell_profile.ps1

如果文件不存在,需要新建一个

New-Item -Path $PROFILE -ItemType File -Force

在文件里,添加别名配置

Set-Alias vim nvim

使配置生效:

. $PROFILE