关于 spring-security-configuration
spring-security-configuration 是 Spring Agent Toolkit 中用于生成 Spring Security 配置的技能。它通过 Amplicode 工具获取项目背景,并依据示例处理认证、授权、依赖项和属性。
主要功能
- 01生成 WebSecurity 配置类
- 02配置认证与授权 DSL
- 03根据项目背景确定设置
- 04添加所需依赖项和属性
- 05以示例作为代码依据
适用场景
- 01为 Spring 项目配置 Spring Security
- 02根据认证需求选择配置方案
- 03添加安全属性和依赖项
MCP 相关
需要由 Amplicode IntelliJ 插件提供的 Spring MCP 服务。它使用 Amplicode 工具检查项目摘要、依赖项、属性和现有安全配置。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ amplicode/ spring-skills --skill spring-security-configuration安装后在 Claude Code 中输入/spring-security-configuration确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
examples/_beans/jwt-converter/java.mdkotlin.mdexamples/_beans/ldap-auth-manager/java.mdkotlin.mdexamples/_beans/ldap-context-source/java.mdkotlin.mdexamples/_beans/logout-handler/java.mdkotlin.mdexamples/_beans/role-mapper/java.mdkotlin.mdexamples/_beans/user-storage/java.mdkotlin.mdexamples/_dependencies/authorization-server.mdbase.mdldap.mdoauth-client.mdresource-server.mdexamples/_fragments/anonymous/java.mdkotlin.mdexamples/_fragments/authorize-requests/java.mdkotlin.mdexamples/_fragments/csrf/java.mdkotlin.mdexamples/_fragments/exception-handling/java.mdkotlin.mdexamples/_fragments/form-login/java.mdkotlin.mdexamples/_fragments/headers/java.mdkotlin.mdexamples/_fragments/jwt/java.md详细介绍
预检:Spring MCP
此技能是 Spring Agent Toolkit 的一部分,专为配合 Spring MCP 服务(由 Amplicode IntelliJ 插件提供)使用而设计。在执行任何操作之前,请检查工具列表中是否有 Spring MCP 工具——这些工具通过 amplicode MCP 服务提供(例如,get_project_summary、list_module_dependencies、get_entity_details);将 MCP 工具平铺到工具列表中的运行环境,会在相同名称前加上 mcp__amplicode__ 前缀。
- 如果至少有一个 Amplicode 工具可用——MCP 已连接。继续执行以下技能。
- 如果没有可用工具——停止并调用
amplicode-install技能(随 Spring Agent Toolkit 一同提供)。该技能会安装 Amplicode 插件,并引导用户点击欢迎屏幕上的 «Настроить Spring Agent» 按钮,然后重启 MCP 客户端。完成后,MCP 工具即可使用——继续执行此技能。 - 如果技能列表中未注册
amplicode-install,请用用户的语言告知他们:"此技能需要 Amplicode IntelliJ 插件及其 MCP 服务。请从 https://amplicode.ru/marketplace 将其安装到 IntelliJ IDEA Ultimate/Community 或 GigaIDE 中,打开任意项目,点击 Amplicode 欢迎屏幕上的 «Настроить Spring Agent»,然后重启 MCP 客户端。"
Spring Security 配置
生成一个 @Configuration @EnableWebSecurity 类,其中包含 filterChain() 方法、用于身份验证和授权的 DSL 链、Bean、依赖项,以及 application.properties 中的属性。
重要:仅根据 examples/ 文件中的示例编写代码。如果没有匹配的示例——停止并询问用户。 重要:对于有固定选项的问题,优先使用
AskUserQuestion> 其同类工具 > 纯文本列表。只有在没有可用交互工具时,才使用普通的编号文本列表作为最后手段。 重要:运行步骤 1 之前,请阅读对话上下文。步骤 2–3 中一半的问题可能已由用户的提示和之前的对话回答。重复询问已说明的内容是此技能显得缓慢的首要原因。
默认值
| 选项 | 默认值 | 是否始终询问? | 备注 |
|---|---|---|---|
| 身份验证类型 | — | 是 | 主要分支条件 |
| 禁用 CSRF | 否 | 否 | |
| 禁用标头 | 否 | 否 | |
| 禁用匿名访问 | 否 | 否 | |
| 授权规则 | anyRequest().authenticated() | 否 | |
| language | 来自 get_project_summary | 否 | 自动检测 |
| bootVersion | 来自 get_project_summary | 否 | 自动检测 |
| className | SecurityConfiguration | 否 | 提议,仅需确认 |
| packageName | 与现有 @Configuration 相同 | 否 | 自动检测 |
| appPrefix | 来自现有的 @Value 属性或 app | 否 | 根据项目自动检测 |
智能默认值: 如果用户说“使用默认值”“全部默认值”“默认设置”或类似表达,则跳过所有“是否始终询问?”为“否”的问题。只询问必答问题。
智能识别回答: 当用户直接提供值,而不是从编号列表中选择时,直接接受该值。示例:
- 问题“身份验证类型?”→ 用户回答“jwt”→ 这就是选择,不要显示选项
- 问题“客户端 ID?”→ 用户回答“my-app”→ 这就是值,不要再次询问
- 如果用户在一条消息中提供多个回答,则全部接受,并跳过已回答的问题
- 绝不要询问用户已经回答过的问题(包括隐含回答)
批量提问: 将密切相关的问题合并到一次
AskUserQuestion 调用中(每次最多 4 个问题),前提是它们:
- 属于同一逻辑部分(例如,都是连接设置)
- 不依赖彼此的回答
- 有明显的默认值,用户可以跳过
规则:
- 每次
AskUserQuestion调用最多包含 3-4 个问题 - 为推荐选项标注
(Recommended),并将其放在首位 - 绝不批量合并来自不同决策分支的问题
- 主要分支问题(身份验证类型)始终单独询问
- 选择时优先使用
AskUserQuestion;只有在工具不可用时,才使用纯文本列表
决策原则——先看上下文,再提问
在向用户提出任何问题之前,先尝试从已收集的上下文中推导答案:项目摘要、模块依赖项、现有安全配置、此对话之前的轮次,以及用户最初的提示词。只有当上下文无法得出明确的默认值,或选择确实取决于用户(例如身份验证类型、授权规则)时,才提问。
决策层级:
-
上下文明确无误 → 静默决定,不要提问。 示例:从
get_project_summary获取 language 和 Boot 版本;从list_module_dependencies获取现有依赖项;从现有的@Configuration类获取 packageName;className =SecurityConfiguration;从现有的@Value注解获取 appPrefix。 -
上下文提供了强烈信号 → 用一行说明决定和替代选项,让用户选择更改或不作回应。 格式:
Will create SecurityConfiguration with JWT (spring-boot-starter-oauth2-resource-server found in dependencies). Alternatives: Form Login, OIDC, LDAP, Custom. OK?用户可以回答“ok”/“yes”或不作回应 → 接受;也可以指定替代选项 → 切换。
-
上下文无法得出明确的默认值 → 使用
AskUserQuestion提问(优先),并将推荐选项放在首位。 在推荐选项的标签中标注(Recommended),并将其放在首位。如果没有可用的交互式选择工具,则改用纯文本列表。 -
关键输入的上下文完全为空 → 直接提问。 适用于:身份验证类型(依赖项无法提供线索时)、授权规则、特定变体的设置。
如何提问 — 优先使用 AskUserQuestion
必须提问时,优先使用 AskUserQuestion 工具,而不是在回复正文中编写编号列表。只有在没有可用的交互式选项工具时,才改用纯文本。
在此技能中调用 AskUserQuestion 的规则:
- 每次调用最多可包含 4 个彼此独立的问题。可借此在一次往返中批量处理相关决策。
- 每个问题有 2–4 个选项。该工具会自动添加一个供自由输入的“Other”选项 — 切勿手动添加。
- 将建议选项放在首位,并在标签后加上
(Recommended),以标记该选项。 header是一个 12 字符的标签(例如 "Auth Type"、"CSRF"、"Headers")。
以下情况不适合使用 AskUserQuestion:
- 需要自由输入、没有可枚举选项的内容(例如 URL、客户端 ID、DN、模式)— 请用纯文本提问。
- 原则 2 中的“单行确认” — 这是简单的是/否问题,不是枚举选项。
绝不要向用户索取任何类型的凭据(客户端密钥、管理员密码、API 密钥、令牌等)— 不要通过 AskUserQuestion、纯文本或任何其他形式索取。对于每个凭据字段,技能都会将环境变量占位符(${OAUTH_*_CLIENT_SECRET}、${LDAP_MANAGER_PASSWORD}、${AUTHSERVER_*_CLIENT_SECRET})写入 application.properties,并在生成后向用户说明占位符名称 — 参见各变体参考资料以及 _properties/*/properties.md 中的“secret handling”部分。
步骤 2–3 和参考文件中的问题列表是情况 4 的备用方案。它们不是需要按顺序逐一执行的脚本。如果原则 1–3 已经确定了某个问题的答案,就跳过该问题。
步骤 0 -- 优先检查对话上下文(必需,不调用工具)
在进行任何 MCP 调用或提问之前,重新阅读用户的提示和本次对话此前的内容,提取其中已经说明的信息。此步骤无需成本,可避免此技能最常见的问题 — 询问用户已经提供过的信息。
在心中列出输入清单,并勾选用户已明确或隐含提供的所有内容:
| 输入项 | 在提示/上下文中查找 |
|---|---|
| 身份验证类型 | “JWT”、“表单登录”、“OIDC”、“Keycloak”、“LDAP”、“OAuth2”、“授权服务器” — 任何直接或隐含的提及 |
| 提供方 | “Keycloak”、“Google”、“GitHub”、“Okta”、“AWS Cognito” — 这表示使用 OIDC 或 JWT 变体 |
| 授权规则 | “仅限 ADMIN”、“公开 API”、“所有端点都需授权” |
| 语言 | Kotlin / Java — 也可根据讨论中的文件扩展名推断 |
| className | “将其命名为 SecurityConfig”、“类名 XxxConfiguration” |
| 智能默认值 | “使用默认值”、“全部使用默认值”、“默认设置”、“最小配置” |
| 已有项目信息 | 语言、Boot 版本、依赖项 — 如果本次对话此前已讨论过,则视为已知;不要重新获取 |
对于已明确回答或可强烈推断出答案的每项输入: 将其标记为已确定,并跳过步骤 2–3 中对应的问题。如果用户写了“配置 JWT”,就不要问“身份验证类型是什么?”,因为答案已经是 JWT。如果用户写了“使用 Kotlin”,就不要询问语言。
对于尚未回答的输入:遵循上文的决策原则 — 先尝试根据项目上下文推断(步骤 1),然后再提问。
步骤 0 在心中完成,不是工具调用。不要向用户宣布这一步,也不要写“步骤 0 已完成”。开始步骤 1 之前,只需先在心中确认用户已经提供的信息。
步骤 1 —— 收集上下文(自动执行,不提问)
调用 Spring MCP 工具(尽可能并行调用)。
| 工具 | 提取内容 | 变量名 |
|---|---|---|
get_project_summary | 语言、springBootVersion、moduleName、buildFile、mainPackage | language、bootMajor、moduleName、buildFile、mainPackage |
list_module_dependencies(moduleName) | artifact ID | presentDeps |
list_application_properties_files(moduleName) | 属性文件路径 | propsFile |
list_security_configurations | 现有安全配置 | existingConfigs |
list_spring_security_roles | 授权规则的现有角色 | existingRoles |
如果是多模块项目(get_project_summary 中包含多个模块):
询问要使用哪个模块。然后使用该模块重新调用特定模块的 MCP 工具。
如果 existingConfigs 不为空:
- 提醒用户:“项目已有安全配置:{list}。是否创建其他配置?”
- 如果用户确认 — 建议一个不会与现有名称冲突的
{className} - 如果用户拒绝 — 停止
确定 appPrefix:扫描项目中现有的 @Value 注解,查找常见的自定义前缀
(例如,@Value("${myapp.something}") → appPrefix = myapp)。如果没有,则默认为 app。
步骤 2 —— 身份验证类型
询问:
Authentication type?
1. Form Login (HTTP Session) -- form login with session
2. JWT (OAuth2 Resource Server) -- stateless JWT
3. OAuth2/OIDC Login -- login via external provider (Keycloak, Google, GitHub...)
4. Authorization Server -- own authorization server (Spring Boot >= 3.1)
5. LDAP -- LDAP authentication
6. Custom -- empty filterChain, only common DSL blocks
将回答映射到参考文件:
- 1 ->
references/http-session.md - 2 ->
references/jwt.md - 3 ->
references/oidc.md - 4 ->
references/authorization-server.md(要求 bootMajor >= 3.1——如果低于此版本,提醒用户并请其选择其他类型) - 5 ->
references/ldap.md - 6 ->
references/custom.md
步骤 3 —— 特定变体的问题(内联)
读取映射的参考文件,并按照其中的问题流程执行。 仅当用户没有说“全部使用默认值”时才询问。
每个参考文件都会指定:
- 要包含哪些片段
- 要生成哪些 bean
- 要添加哪些依赖
- 要写入哪些属性
- 特定变体的问题
步骤 4 -- 生成代码
-
从
examples/_skeletons/{lang}.md读取骨架,其中{lang}=java或kotlin(来自步骤 1) -
使用骨架创建配置类文件,并替换
{packageName}和{className} -
读取所选变体的参考文件。对于其中列出的每个片段:
- 从
examples/_fragments/{feature}/{lang}.md读取片段文件 - 将相应的代码变体插入 filterChain 方法体中,位置在
return http.build();之前 - 根据步骤 1 中的
bootMajor选择正确的版本变体(某些片段包含 Boot < 3.1 / Boot >= 3.1 部分——使用匹配的部分) - 应用变量替换(仅限 Variables 部分中声明的变量)
- 仅包含符合用户所选选项的行(跳过注释掉的条件行)
- 从
-
filterChain 方法内 DSL 的顺序(重要):
关于每种变体的确切顺序,请参阅
references/common-dsl.md→ “Generation Order”。 始终以return http.build();结尾。 -
对于参考文件中列出的每个 Bean:
- 从
examples/_beans/{bean-type}/{lang}.md读取 Bean 文件 - 将 Bean 方法添加到配置类主体中
- 关键:每个 Bean 方法都必须在 filterChain DSL 中被引用。 不要创建未使用的方法。
- 如果 Bean 需要自动装配字段(例如
clientRegistrationRepository),请将它们添加到类中
- 从
-
变量替换规则:
{packageName}-> 来自步骤 1 的上下文{className}-> 来自用户输入或默认值- 其他变量 -> 来自用户回答或默认值
- 绝不替换 Variables 中未列出的内容
- 绝不添加示例中没有的导入、方法或代码
- 仅在导入中使用 FQN,代码主体保持简洁。 示例可能包含行内全限定名(例如
new org.springframework.security.web.SecurityFilterChain(...))。 生成代码时,将 FQN 提取为导入语句,并在代码主体中使用简短类名。 生成的文件应与手写代码风格一致。
步骤 5 -- 依赖项与属性(自动处理)
- 读取
_dependencies/base.md(始终读取) - 读取特定变体的依赖文件(来自参考文件)
- 根据步骤 1 中的
bootMajor选择正确的版本变体:- 依赖文件包含 Boot 3.x / Boot 4.x 部分——使用与
bootMajor匹配的部分 - Boot 4.x 更改了 OAuth2 构件名称:
spring-boot-starter-oauth2-*→spring-boot-starter-security-oauth2-* - Boot 3.0 上的 Authorization Server 需要手动添加
spring-security-oauth2-authorization-server:1.1.0(无 starter)
- 依赖文件包含 Boot 3.x / Boot 4.x 部分——使用与
- 对于
presentDeps中未包含的每个构件:- 使用步骤 1 中的
buildFile - 编辑构建文件以添加依赖项
- 使用步骤 1 中的
- 调用
refresh_build_system_model - 从
_properties/{variant}/properties.md读取特定变体的属性文件 - 写入/追加到应用属性文件
- 报告:“已添加依赖项:[列表]。已写入 application.properties:[键]”
- 如果生成的属性中包含用于凭据的任何
${...}环境变量占位符(OAUTH_*_CLIENT_SECRET、LDAP_MANAGER_PASSWORD、AUTHSERVER_*_CLIENT_SECRET),请明确列出每个占位符,并指示用户在运行应用前设置这些环境变量(使用 shellexport、IDE 运行配置或部署密钥存储)。绝不要向用户索要密钥值本身——密钥不得进入对话历史。
防幻觉检查清单
编写任何代码之前,请确认:
- 代码来自某个
examples/文件(注明具体文件) - 仅替换了已声明的变量
- 没有“凭记忆”添加框架 API 调用
- 导入项均根据示例中使用的 FQN 提取(无多余或缺失)
- 方法签名与示例完全一致
- 没有添加注释或便利方法
- 从示例中提取 FQN 并写入导入项;代码主体仅使用类名简写
-
filterChain中 DSL 的顺序遵循 Step 4 中定义的变体专属顺序(HTTP Session/JWT:先调用authorizeHttpRequests;OIDC:先调用oauth2Login,再调用logout,最后调用authorizeHttpRequests) - 辅助方法(
jwtAuthenticationConverter、oidcClientInitiatedLogoutSuccessHandler)不是@Bean,而是由filterChain直接调用的公共方法。注意:通用提供方的userAuthoritiesMapper是@Bean,但 Keycloak 的不是(参见角色映射器 Bean 文件) - 生成的每个 Bean 方法都确实由
filterChainDSL 或其他 Bean 引用,不存在孤立方法 - 对于 HTTP Session:如果配置了用户存储,
filterChain中须包含http.userDetailsService(...)调用 - 对于 HTTP Session:只有设置了非默认登出选项时才生成登出 DSL(Spring Security 会自动启用默认登出)
- 特定版本的代码/依赖项与
bootMajor匹配:Boot 4.x 使用spring-boot-starter-security-oauth2-*(而非spring-boot-starter-oauth2-*);Boot 3.1 中会话管理并发会话 API 已变更