04Java · Spring Boot · SQLiteJava · Spring Boot · SQLite

accc-Libra

A Spring Boot web app: a captcha-verified public page, a password-protected admin page with single entry and CSV batch import, and SQLite storage created on startup.一个 Spring Boot Web 应用:带人机验证的公开页、有口令保护的管理页(单条录入和 CSV 批量导入),以及启动时自动建表的 SQLite 存储。

My role我的角色
Sole author.独立作者。
Status状态
Private repo私有仓库
# application.yaml — every secret can be overridden
spring.datasource.url: jdbc:sqlite:app.db
spring.sql.init.mode: always   # schema on start
captcha.id:  ${CAPTCHA_ID}
captcha.key: ${CAPTCHA_KEY}
admin.token: ${ADMIN_TOKEN}
22pages: public and admin个页面:公开页和管理页
11jar to run, schema created on start个 jar 即可运行,启动时建表
envenvoverrides for every secret变量覆盖所有密钥

01The problem问题

A small service that has to be safe by default.一个小服务,也得默认安全。

Bots on the public page公开页上的机器人

A public endpoint that hands out records must make sure a person, not a script, is asking.对外提供记录的公开接口,必须确认是人在请求,而不是脚本。

Bulk data entry批量录入

The admin needs to add one record quickly, or hundreds from a spreadsheet, without breaking existing data.管理员既要能快速加一条,也要能从表格一次导入几百条,而且不能破坏已有数据。

Zero setup零配置部署

It should run from one jar with no database server to install.应该一个 jar 就能跑,不需要另装数据库服务。

02What I built我做了什么

Spring Boot, SQLite, and a captcha gate.Spring Boot、SQLite 和一道人机验证。

A Spring Boot app with two pages: a public page gated by Geetest v4 captcha verification on the server, and a password-protected admin page. SQLite holds the data, and the schema is created on startup.一个有两个页面的 Spring Boot 应用:公开页由服务端校验 Geetest v4 人机验证,管理页有口令保护。数据存在 SQLite,启动时自动建表。

  • Server-side captcha check: the page sends the challenge result; the server verifies it with the provider before doing anything.服务端校验人机验证:页面提交验证结果,服务端先向验证服务确认,再做任何操作。
  • Admin page with single entry and CSV batch import, validated row by row.管理页支持单条录入和 CSV 批量导入,逐行校验。
  • Every secret can be overridden by an environment variable, so nothing sensitive needs to live in the repo.所有密钥都能用环境变量覆盖,敏感信息不需要放进仓库。
  • 51 JUnit test classes, plus Python tooling with its own tests.51 个 JUnit 测试类,另有带测试的 Python 工具。

03How it works怎么做的

Two doors into one database.两扇门,通向同一个数据库。

  1. STEP 01

    Public page公开页

    Static HTML + JS, captcha widget.静态 HTML + JS,人机验证组件。

  2. STEP 02

    Captcha verify人机验证

    Server checks the token with Geetest v4.服务端向 Geetest v4 校验令牌。

  3. STEP 03

    Spring serviceSpring 服务

    Controllers, validation, transactions.控制器、校验、事务。

  4. STEP 04

    SQLiteSQLite

    One file; schema created on start.一个文件;启动时建表。

  5. STEP 05

    Admin page管理页

    Token-protected; single entry or CSV import.口令保护;单条录入或 CSV 导入。

05Tech used用到的技术

What it’s made of.用什么做的。

Server服务端
  • Java 17
  • Spring Boot
  • Maven
Data数据
  • SQLite
  • JDBC
  • CSV
Security安全
  • Geetest v4
  • env overrides环境变量覆盖
  • token-protected admin口令保护的管理页
Quality质量
  • 51 JUnit test classes51 个 JUnit 测试类
  • Private repository私有仓库

06What I learned我学到了什么

Lessons I’ll keep.会一直记得的几件事。

  1. Never trust the browser. The captcha result is only a claim until the server verifies it; the first version learned this the hard way in testing.永远别信浏览器。人机验证的结果在服务端确认之前只是一个说法;第一版在测试里吃过这个亏。
  2. Imports need a dry run. Validating every CSV row before writing any made bulk import boring, which is what you want.导入要先试跑。先校验 CSV 的每一行、再写入任何一条,批量导入就变得很无聊,这正是想要的。
  3. The simplest database that works. SQLite meant one file to back up and no server to run.用够用的最简单数据库。SQLite 意味着只需要备份一个文件,也不用运行数据库服务。