
1. 从零搭建 Spring Boot 用户授权登陆oh-my-opencode 实战场景拆解用户授权登陆这件事说简单也简单说麻烦也麻烦。简单在于核心逻辑无非是「查用户、比密码、发凭证」麻烦在于要把它写规范——密码不能明文存、接口要能调试、登陆后要能校验身份。很多刚接触 Spring Boot 的朋友卡在第一步项目骨架怎么搭、MyBatis-Plus 怎么配、Swagger UI 怎么开、Password 加密和 Bearer 校验怎么串起来。这篇内容就是围绕这个场景展开的。我会用 oh-my-opencode 作为辅助工具从空目录开始一步步搭出一个带前端登陆页、后端 Swagger UI 调试、Password 加密存储、Bearer 令牌校验的 Spring Boot 项目。适合谁看适合已经会一点 Java、想快速跑通「用户授权登陆」全链路、又不想在环境配置上耗太久的人。你不需要提前准备什么复杂环境JDK 17 加一个能联网的终端就够了。核心检索词先明确oh-my-opencode 是一个命令行里的 AI 编码助手能根据自然语言指令生成项目结构、代码和配置Spring Boot 是后端框架MyBatis-Plus 负责数据库操作Swagger UI 提供接口可视化调试Password 加密和 Bearer 校验负责安全。这几个词会贯穿全文。我试过直接手写这套东西光是 pom 依赖和 MyBatis-Plus 的配置就来回改了好几遍。后来换成用 oh-my-opencode 先出骨架再自己补细节效率高不少。下面我把整个过程拆成可复制的步骤你跟着做就行。先说一下整体思路第一步用 oh-my-opencode 生成 Spring Boot MyBatis-Plus 的基础项目第二步补上用户表的实体、Mapper 和 CRUD第三步加 Swagger UI 注解第四步写登陆接口用 BCrypt 做 Password 加密存储登陆成功后发一个简单 Bearer 令牌第五步启动项目用 Swagger UI 和前端页面分别验证。每一步都有具体命令和代码。在开始之前你需要确认本地有 JDK 17 或更高版本Maven 能正常拉依赖。终端里输入java -version和mvn -v检查一下。如果 Maven 没装去官网下个二进制包解压配一下 PATH 就行。数据库这块为了减少外部依赖我建议先用 H2 内存数据库跑通流程后面再换 MySQL。这样你不需要额外装数据库服务启动就能用。oh-my-opencode 的安装方式这里不展开假设你已经能在终端里调用它。如果你还没装可以先去它的文档看一眼装好后在项目目录里输入ulw就能进入交互模式。接下来所有生成动作都在这个模式里完成。2. TaoToken 前置准备模型接入与 API Key 配置在让 oh-my-opencode 干活之前得先解决模型接入的问题。oh-my-opencode 本身是个壳背后要调大模型来生成代码。这里用 TaoToken 做模型接入层它提供统一的 API 入口支持多种模型切换。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 。为什么需要这一步因为 oh-my-opencode 在生成项目时会频繁调用模型来理解你的指令、输出代码。如果模型接入不稳定生成到一半断了项目结构就会残缺。TaoToken 的好处是它把不同模型的调用统一成一套接口你只需要配一次 Base URL 和 Key后面切换模型只改一个 Model ID 就行。具体操作先注册并登录 TaoToken 控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。进去之后找到 API Keys 页面新建一个 Key复制出来。这个 Key 就是后面配置里的凭证。注意 Key 只显示一次复制后存好。然后配置 oh-my-opencode 的模型接入。它通常有一个配置文件路径可能是~/.oh-my-opencode/config.json或者项目根目录下的.opencode/config.json。具体看你安装的版本用oh-my-opencode --help查一下配置路径。配置文件里需要填三个东西Base URL、API Key、Model ID。Base URL 填https://taotoken.net/apiAPI Key 填你刚复制的Model ID 填你想用的模型比如MiniMax-M2.1或者claude-opus-4-6-thinking。这里给一个可复制的 JSON 配置片段路径按你实际的配置文件位置来{ provider: taotoken, baseUrl: https://taotoken.net/api, apiKey: sk-你的Key粘贴在这里, model: MiniMax-M2.1, maxTokens: 8192, temperature: 0.3 }如果你用的是 TOML 格式的配置等价写法是[provider] name taotoken base_url https://taotoken.net/api api_key sk-你的Key粘贴在这里 model MiniMax-M2.1 max_tokens 8192 temperature 0.3配好之后在终端里跑一个测试请求确认能通。可以用 curl 直接打 APIcurl -X POST https://taotoken.net/api/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer sk-你的Key \ -d { model: MiniMax-M2.1, messages: [{role: user, content: 回复ok}], max_tokens: 10 }如果返回里有choices字段且内容正常说明接入成功。如果报 401检查 Key 有没有复制错、有没有多余空格。如果报 model not found检查 Model ID 拼写。这一步通了后面 oh-my-opencode 才能正常生成代码。关于模型选择如果你要做长期编码任务可以考虑 Coding Plan地址是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。它针对编码场景做了优化调用额度更充裕。如果只是临时验证模型效果用模型对话页面就行https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。配置完成后回到你的工作目录准备开始生成项目。3. 可复制配置用 oh-my-opencode 生成 Spring Boot 项目骨架现在进入实操。打开终端cd 到一个空目录比如~/workspace。输入ulw进入 oh-my-opencode 交互模式。第一条指令我建议这样写在当前目录中新建一个项目名为 OhMyProject 的 Spring Boot 项目使用 Spring Boot 3.2.x 最新稳定版集成 MyBatis-Plus数据库先用 H2 内存库并生成一个 README 文件说明项目结构和启动方式。回车后等几分钟。oh-my-opencode 会先规划目录结构然后逐个生成文件。你会看到它创建了pom.xml、src/main/java/...、application.yml等。生成完毕后用tree或find看一下结构应该是标准的 Maven 布局。接下来检查pom.xml里的依赖。关键依赖包括spring-boot-starter-web、mybatis-plus-boot-starter、h2、spring-boot-starter-validation、springdoc-openapi-starter-webmvc-ui这是 Swagger UI 的新版依赖旧版是 springfox别用错了。如果 oh-my-opencode 生成的版本不对手动改一下。给一个可复制的依赖片段dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.5/version /dependency dependency groupIdcom.h2database/groupId artifactIdh2/artifactId scoperuntime/scope /dependency dependency groupIdorg.springdoc/groupId artifactIdspringdoc-openapi-starter-webmvc-ui/artifactId version2.3.0/version /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-validation/artifactId /dependency /dependencies然后看application.yml确保 H2 和 MyBatis-Plus 配置正确server: port: 8080 spring: datasource: url: jdbc:h2:mem:ohmyproject;DB_CLOSE_DELAY-1 driver-class-name: org.h2.Driver username: sa password: h2: console: enabled: true path: /h2-console sql: init: mode: always mybatis-plus: configuration: map-underscore-to-camel-case: true global-config: db-config: id-type: auto这里spring.sql.init.mode: always会让 Spring Boot 启动时执行schema.sql和data.sql。我们需要建用户表并插一条测试数据。在src/main/resources下新建schema.sqlCREATE TABLE IF NOT EXISTS sys_user ( id BIGINT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(64) NOT NULL UNIQUE, password VARCHAR(128) NOT NULL, nickname VARCHAR(64), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );再建data.sql插入一个测试用户。注意密码这里先放明文占位后面登陆逻辑里会用 BCrypt 校验所以实际存的时候要存 BCrypt 哈希。为了演示方便我先在 data.sql 里存一个已知哈希对应明文123456INSERT INTO sys_user (username, password, nickname) VALUES (admin, $2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iKTVKIUi, 管理员);这个哈希是 BCrypt 对123456加密的结果后面登陆时用BCryptPasswordEncoder.matches(123456, hash)能匹配上。接下来生成实体和 Mapper。在 ulw 里继续输入在 OhMyProject 中创建 SysUser 实体类对应 sys_user 表字段包括 id、username、password、nickname、createdAt使用 MyBatis-Plus 注解。再创建 SysUserMapper 接口继承 BaseMapper并写一个根据用户名查询用户的方法。生成后检查代码。实体类大概长这样package com.example.ohmyproject.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import java.time.LocalDateTime; TableName(sys_user) public class SysUser { TableId(type IdType.AUTO) private Long id; private String username; private String password; private String nickname; private LocalDateTime createdAt; // getter 和 setter 省略实际生成时会有 }Mapper 接口package com.example.ohmyproject.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.example.ohmyproject.entity.SysUser; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; Mapper public interface SysUserMapper extends BaseMapperSysUser { Select(SELECT * FROM sys_user WHERE username #{username}) SysUser selectByUsername(String username); }到这里项目骨架和数据层就齐了。下一步加 Swagger UI 注解和登陆接口。4. 验证请求与成功结果Swagger UI 调试登陆接口先补 Swagger UI 的配置。在 ulw 里输入给 OhMyProject 添加 Swagger UI 配置类启用 OpenAPI 文档并给用户相关的 Controller 加上 Tag 和 Operation 注解。生成后检查配置类应该有一个OpenApiConfig或者直接在application.yml里配springdoc。确保springdoc.api-docs.path和springdoc.swagger-ui.path有值默认是/v3/api-docs和/swagger-ui.html。然后写登陆接口。在 ulw 里输入在 OhMyProject 中创建 AuthController提供一个 POST /api/auth/login 接口接收 username 和 password用 BCryptPasswordEncoder 校验密码校验通过后生成一个简单的 Bearer 令牌返回令牌可以用 UUID 加时间戳。同时提供一个 GET /api/auth/me 接口从 Authorization 头里读取 Bearer 令牌返回当前用户信息。生成后检查AuthController。核心逻辑大概是这样package com.example.ohmyproject.controller; import com.example.ohmyproject.entity.SysUser; import com.example.ohmyproject.mapper.SysUserMapper; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; import java.util.UUID; Tag(name 认证接口, description 用户登陆与令牌校验) RestController RequestMapping(/api/auth) public class AuthController { Autowired private SysUserMapper sysUserMapper; private final BCryptPasswordEncoder encoder new BCryptPasswordEncoder(); Operation(summary 用户登陆, description 传入用户名和密码返回 Bearer 令牌) PostMapping(/login) public ResponseEntity? login(RequestBody MapString, String body) { String username body.get(username); String password body.get(password); SysUser user sysUserMapper.selectByUsername(username); if (user null || !encoder.matches(password, user.getPassword())) { return ResponseEntity.status(401).body(Map.of(error, 用户名或密码错误)); } String token UUID.randomUUID().toString().replace(-, ); MapString, Object result new HashMap(); result.put(token, token); result.put(username, user.getUsername()); result.put(nickname, user.getNickname()); return ResponseEntity.ok(result); } Operation(summary 获取当前用户, description 从 Authorization 头读取 Bearer 令牌) GetMapping(/me) public ResponseEntity? me(RequestHeader(value Authorization, required false) String auth) { if (auth null || !auth.startsWith(Bearer )) { return ResponseEntity.status(401).body(Map.of(error, 缺少 Bearer 令牌)); } String token auth.substring(7); // 演示用实际应查缓存或数据库 return ResponseEntity.ok(Map.of(token, token, message, 令牌有效)); } }注意这里为了演示简单令牌没有存起来/me接口只校验格式。生产环境要把令牌存 Redis 或数据库并设过期时间。现在启动项目。在 ulw 里输入启动该项目或者直接在终端跑mvn spring-boot:run。等控制台出现Started OhMyProjectApplication就说明起来了。打开浏览器访问http://localhost:8080/swagger-ui.html能看到 Swagger UI 页面。找到认证接口分组展开POST /api/auth/login点Try it out填入{ username: admin, password: 123456 }点 Execute预期返回 200body 里有token、username、nickname。如果返回 401说明密码没匹配上检查 data.sql 里的哈希是不是对应123456。再测GET /api/auth/me在 Authorization 头里填Bearer 你刚拿到的tokenExecute 后应该返回令牌有效的信息。前端登陆页面这块oh-my-opencode 可以生成一个简单的 HTML 页面放在src/main/resources/static/login.html用 fetch 调/api/auth/login成功后把 token 存 localStorage再跳转到主页。你可以让 ulw 生成在 OhMyProject 的 static 目录下生成 login.html包含用户名和密码输入框、登陆按钮点击后调用 /api/auth/login成功后把 token 存 localStorage 并显示欢迎信息。生成后访问http://localhost:8080/login.html就能看到页面。输入 admin / 123456点登陆页面会显示欢迎信息。到这里从 Password 加密存储到 Swagger UI 调试再到前端登陆全链路就跑通了。5. 本篇常见错排查401、local proxy failed 与 reading choices 报错实操过程中最容易撞的几个坑我逐个列出来你对照着排查。第一个是 401 Unauthorized。分两种场景一种是调 TaoToken API 时返回 401说明 API Key 不对。检查配置文件里的apiKey有没有多余空格、有没有过期、有没有复制错。可以在终端用 curl 单独测一下排除 oh-my-opencode 配置文件的干扰。另一种是调/api/auth/login返回 401说明用户名或密码不匹配。检查 data.sql 里的 BCrypt 哈希是不是对应你输入的明文。BCrypt 每次加密结果不同但matches能校验。如果你自己生成哈希用这段代码BCryptPasswordEncoder encoder new BCryptPasswordEncoder(); String hash encoder.encode(123456); System.out.println(hash);把输出的哈希替换到 data.sql 里。第二个是local proxy failed。这个报错通常出现在 oh-my-opencode 调模型时网络请求没发出去。检查你的 Base URL 是不是https://taotoken.net/api注意末尾不要多斜杠。如果公司网络有防火墙确认能访问外网。另外检查配置文件里的 provider 名称和实际调用的是否一致。有些版本的 oh-my-opencode 需要显式指定provider: taotoken漏了会走默认 provider 导致失败。第三个是reading choices报错。这个一般出现在解析模型响应时返回的 JSON 里没有choices字段。原因可能是模型名写错了比如把MiniMax-M2.1写成minimax-m2.1大小写敏感。也可能是请求体格式不对比如messages数组为空。用 curl 测一下curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer sk-你的Key \ -d {model:MiniMax-M2.1,messages:[{role:user,content:hi}]}如果 curl 能返回正常 JSON说明 Key 和模型没问题那就是 oh-my-opencode 的配置解析有误。检查它的配置文件里model字段有没有被其他配置覆盖。第四个是 OAuth 相关报错。如果你在配置里用了 OAuth 流程但回调地址没配好会报OAuth callback mismatch。TaoToken 的 API Key 方式是直接 Bearer 认证不需要 OAuth所以如果你看到 OAuth 报错大概率是配置文件里混入了其他 provider 的配置。把配置文件清理一下只保留 TaoToken 相关的字段。第五个是 Swagger UI 打不开。访问/swagger-ui.html返回 404检查pom.xml里有没有springdoc-openapi-starter-webmvc-ui依赖版本是不是 2.x。Spring Boot 3.x 必须用 springdoc 2.x用 1.x 会不兼容。另外检查application.yml里有没有把springdoc.api-docs.enabled设成 false。第六个是 H2 控制台连不上。访问/h2-console时JDBC URL 要填jdbc:h2:mem:ohmyproject用户名sa密码留空。如果报数据库不存在检查application.yml里的spring.datasource.url和 H2 控制台填的是不是一致。排查顺序建议先确认 TaoToken API 能通再确认项目能启动最后确认接口能调通。每一步用最小请求验证不要一上来就调复杂接口。6. 语义一致 CTA把登陆模块接到真实项目里跑通这个 demo 之后你手里就有了一套可复用的用户授权登陆模块。接下来可以做的扩展把 H2 换成 MySQL把令牌存 Redis 并加过期时间用 Spring Security 做更细粒度的权限控制前端换成 Vue 或 React 调接口。如果你在接入模型时遇到问题或者想换更稳定的模型跑长期编码任务可以看这几个入口。API Key 管理和接入文档在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 和 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。想先验证模型效果用模型对话页面https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。长期做编码和 Agent 任务Coding Plan 更合适https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。最后说一个我踩过的坑oh-my-opencode 生成代码时如果指令太模糊它会按自己的理解补全结果可能和你预期不一致。比如你说「加个登陆」它可能只生成一个空方法。指令里把接口路径、请求方法、参数名、返回结构都写清楚生成质量会高很多。另外生成后一定要自己读一遍代码尤其是安全相关的部分别直接上生产。