RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/Cursor rules/xin-lai/CodeSpirit

Cursor rule

.cursor/rules/security.mdc

CodeSpirit 安全规范 - 权限系统、审计实体、多租户隔离、数据保护

Cursor rules

Quality

54/100

Scores the file, not the repository.

Length

777 words

27 headings · 16 code blocks

Repository

56

— · pushed 134 days ago

Last changed

3 days ago

First indexed 3 days ago.
xin-lai/CodeSpirit/.cursor/rules/security.mdcRawGitHub
1---
2description: CodeSpirit 安全规范 - 权限系统、审计实体、多租户隔离、数据保护
3globs:
4 - "**/Entities/**/*.cs"
5 - "**/*Entity*.cs"
6 - "**/Authorization/**/*.cs"
7 - "*Service*.cs"
8alwaysApply: false
9---
10 
11# 安全规范
12 
13> 📖 控制器级别的安全特性(`[Authorize]`、`[AllowAnonymous]`、`[NoAudit]`、`[Audit]`)参见 [controller.mdc](mdc:.cursor/rules/controller.mdc)
14 
15## 权限系统架构
16 
17### 权限代码格式
18 
19权限代码由系统自动生成,格式为:`{module}_{controller}_{action}`
20 
21```
22exam_questions_getList // 考试模块-题目控制器-获取列表
23identity_users_create // 身份模块-用户控制器-创建
24```
25 
26### PermissionAttribute 特性
27 
28用于自定义权限名称、描述和继承关系:
29 
30```csharp
31using CodeSpirit.Core.Attributes;
32 
33[HttpPut("{id}")]
34[Permission(
35 Name = "exam_questions_update", // 自定义权限代码
36 DisplayName = "更新题目", // 显示名称
37 Description = "允许更新题目内容", // 权限描述
38 Parent = "exam_questions", // 父级权限
39 AllowInheritedPermissions = new[] { "exam_questions_manage" } // 继承权限
40)]
41[DisplayName("更新题目")]
42public async Task<ActionResult<ApiResponse<QuestionDto>>> Update(
43 long id, [FromBody] UpdateQuestionDto dto)
44{
45 // 拥有 exam_questions_manage 权限的用户也可以执行此操作
46}
47```
48 
49### 权限继承机制
50 
51`AllowInheritedPermissions` 允许配置权限继承,用户拥有任一继承权限时可访问当前接口:
52 
53```csharp
54// 方法级别继承
55[Permission(AllowInheritedPermissions = new[] { "Question.Manage", "Question.Admin" })]
56public async Task<ActionResult> UpdateQuestion(long id) { }
57```
58 
59### IHasPermissionService
60 
61服务层权限检查:
62 
63```csharp
64public class QuestionService : IScopedDependency
65{
66 private readonly IHasPermissionService _permissionService;
67 
68 public QuestionService(IHasPermissionService permissionService)
69 {
70 _permissionService = permissionService;
71 }
72 
73 public async Task<bool> CanManageQuestionAsync()
74 {
75 // 检查用户是否拥有指定权限
76 return _permissionService.HasPermission("exam_questions_manage");
77 }
78
79 public async Task<bool> CanAccessModuleAsync()
80 {
81 // 检查导航权限(仅检查一二级权限)
82 return _permissionService.HasNavigationPermission("exam_questions");
83 }
84}
85```
86 
87## 审计实体
88 
89### AuditableEntityBase
90 
91实体继承 `AuditableEntityBase<TKey>` 自动记录审计信息:
92 
93```csharp
94using CodeSpirit.Shared.Entities;
95 
96public class Question : AuditableEntityBase<long>, IMultiTenant
97{
98 // 自动记录以下字段(由框架自动填充):
99 // - CreatedBy (long) 创建人ID
100 // - CreatedAt (DateTime) 创建时间
101 // - UpdatedBy (long?) 更新人ID
102 // - UpdatedAt (DateTime?) 更新时间
103 // - IsDeleted (bool) 软删除标记
104 // - DeletedBy (long?) 删除人ID
105 // - DeletedAt (DateTime?) 删除时间
106
107 public string Content { get; set; } = string.Empty;
108 public string TenantId { get; set; } = string.Empty; // 多租户支持
109}
110```
111 
112### 实体审计接口
113 
114| 接口 | 说明 | 包含字段 |
115|-----|------|---------|
116| `ICreatable` | 创建审计 | `CreatedBy`, `CreatedAt` |
117| `IUpdatable` | 更新审计 | `UpdatedBy`, `UpdatedAt` |
118| `ISoftDelete` | 软删除 | `IsDeleted`, `DeletedBy`, `DeletedAt` |
119| `IFullAuditable` | 完整审计 | 以上全部 |
120 
121## 多租户数据隔离
122 
123### IMultiTenant 接口
124 
125实体实现 `IMultiTenant` 接口,自动应用租户数据过滤:
126 
127```csharp
128using CodeSpirit.Core;
129 
130public class Question : AuditableEntityBase<long>, IMultiTenant
131{
132 public string TenantId { get; set; } = string.Empty; // 注意:类型为 string
133 public string Content { get; set; } = string.Empty;
134}
135```
136 
137### 租户过滤行为
138 
139```csharp
140// 查询时自动应用租户过滤器,无需手动添加 Where 条件
141public async Task<List<QuestionDto>> GetListAsync()
142{
143 var entities = await _dbContext.Questions
144 .ToListAsync(); // ✅ 自动过滤当前租户的数据
145 return _mapper.Map<List<QuestionDto>>(entities);
146}
147 
148// ❌ 禁止:手动添加租户过滤(除非明确需要跨租户查询)
149public async Task<List<QuestionDto>> GetListAsync()
150{
151 var entities = await _dbContext.Questions
152 .Where(q => q.TenantId == _currentTenant.Id) // 不需要
153 .ToListAsync();
154}
155```
156 
157## 数据保护
158 
159### 排除敏感字段
160 
161DTO 中排除不应返回给客户端的字段:
162 
163```csharp
164using Newtonsoft.Json;
165using CodeSpirit.Amis.Attributes.Columns;
166 
167public class UserDto
168{
169 public long Id { get; set; }
170 public string Username { get; set; } = string.Empty;
171
172 [JsonIgnore] // 不在 API 响应中返回
173 public string PasswordHash { get; set; } = string.Empty;
174
175 [IgnoreColumn] // 不在列表表格中显示
176 public string InternalNote { get; set; } = string.Empty;
177}
178```
179 
180### 密码安全存储
181 
182密码必须使用哈希存储,禁止明文:
183 
184```csharp
185// ✅ 正确:存储密码哈希
186user.PasswordHash = _passwordHasher.HashPassword(user, password);
187 
188// ❌ 禁止:明文存储密码
189user.Password = password;
190```
191 
192## SQL 注入防护
193 
194使用 EF Core 参数化查询(默认安全):
195 
196```csharp
197// ✅ 安全:EF Core 自动参数化
198public async Task<Question?> GetByCodeAsync(string code)
199{
200 return await _dbContext.Questions
201 .FirstOrDefaultAsync(q => q.Code == code);
202}
203 
204// ✅ 安全:使用参数化 SQL
205public async Task<List<Question>> SearchAsync(string keyword)
206{
207 return await _dbContext.Questions
208 .FromSqlInterpolated($"SELECT * FROM Questions WHERE Content LIKE {$"%{keyword}%"}")
209 .ToListAsync();
210}
211 
212// ❌ 危险:字符串拼接(禁止)
213public async Task<Question?> GetByCodeAsync(string code)
214{
215 var sql = $"SELECT * FROM Questions WHERE Code = '{code}'"; // SQL 注入风险!
216 return await _dbContext.Questions.FromSqlRaw(sql).FirstOrDefaultAsync();
217}
218```
219 
220## 日志安全
221 
222### 敏感信息脱敏
223 
224日志中禁止记录敏感信息:
225 
226```csharp
227// ✅ 安全:只记录必要信息
228_logger.LogInformation("用户登录: {Username}, IP: {IpAddress}",
229 username,
230 ipAddress);
231 
232// ✅ 安全:使用脱敏字符串
233_logger.LogInformation("API密钥验证: {MaskedKey}",
234 $"{apiKey[..4]}****{apiKey[^4..]}");
235 
236// ❌ 危险:记录密码(禁止)
237_logger.LogInformation("用户登录: {Username}, Password: {Password}",
238 username, password);
239 
240// ❌ 危险:记录完整 Token(禁止)
241_logger.LogInformation("Token: {Token}", token);
242```
243 
244### 异常日志处理
245 
246```csharp
247try
248{
249 await _service.ProcessAsync(data);
250}
251catch (Exception ex)
252{
253 // ✅ 记录异常但不暴露敏感上下文
254 _logger.LogError(ex, "处理数据失败: EntityId={EntityId}", data.Id);
255 throw; // 重新抛出,由统一异常处理器处理
256}
257```
258 
259## CORS 配置
260 
261框架统一配置 CORS,API 项目无需单独配置:
262 
263```csharp
264// CommonApiServiceExtensions 已配置
265app.UseCors("AllowSpecificOriginsWithCredentials");
266```
267 
268自定义配置(仅在特殊需求时):
269 
270```csharp
271// appsettings.json
272{
273 "Cors": {
274 "AllowedOrigins": ["https://yourdomain.com"],
275 "AllowCredentials": true
276 }
277}
278```
279 
280## CSRF/XSS 防护
281 
282- **CSRF**: API 使用 JWT 认证,天然防御 CSRF 攻击
283- **XSS**: AMIS 框架自动转义输出,后端无需手动处理
284 
285## 安全配置
286 
287### JWT 配置
288 
289```json
290{
291 "Jwt": {
292 "SecretKey": "your-secret-key-at-least-32-characters",
293 "Issuer": "CodeSpirit",
294 "Audience": "CodeSpirit",
295 "ExpireMinutes": 120,
296 "RefreshExpireMinutes": 10080
297 }
298}
299```
300 
301### 审计配置
302 
303```json
304{
305 "Audit": {
306 "Enabled": true,
307 "LogRequestParams": true,
308 "LogResponseData": false,
309 "SensitiveData": {
310 "Enabled": true,
311 "SensitiveFieldPatterns": ["password", "token", "apiKey", "secret"],
312 "ExcludedFields": ["password", "newPassword", "confirmPassword"]
313 }
314 }
315}
316```
317 
318## 禁止事项
319 
320| 禁止 | 原因 | 正确做法 |
321|-----|------|---------|
322| 明文存储密码 | 安全风险 | 使用密码哈希 |
323| SQL 字符串拼接 | SQL 注入风险 | EF Core 参数化查询 |
324| 日志记录密码/Token | 信息泄露 | 只记录必要标识信息 |
325| 手动租户过滤 | 可能遗漏 | 使用 `IMultiTenant` 自动过滤 |
326| DTO 返回密码字段 | 信息泄露 | 使用 `[JsonIgnore]` 排除 |
327 
328## 安全检查清单
329 
330- [ ] 实体继承 `AuditableEntityBase` 实现自动审计
331- [ ] 多租户实体实现 `IMultiTenant` 接口
332- [ ] DTO 中使用 `[JsonIgnore]` 排除敏感字段
333- [ ] 密码使用哈希存储
334- [ ] 数据库查询使用 EF Core 参数化(避免 `FromSqlRaw` 拼接)
335- [ ] 日志中不记录密码、Token 等敏感信息
336- [ ] 敏感操作配置权限检查
337- [ ] 定期审查权限配置和审计日志
338 
339## 参考文件
340 
341- 权限特性: [PermissionAttribute.cs](mdc:Src/CodeSpirit.Core/Attributes/PermissionAttribute.cs)
342- 权限服务: [IHasPermissionService.cs](mdc:Src/CodeSpirit.Core/Authorization/IHasPermissionService.cs)
343- 审计实体基类: [AuditableEntityBase.cs](mdc:Src/CodeSpirit.Shared/Entities/AuditableEntityBase.cs)
344- 多租户接口: [IMultiTenant.cs](mdc:Src/CodeSpirit.Core/IMultiTenant.cs)
345- 审计组件: [CodeSpirit.Audit/README.md](mdc:Src/Components/CodeSpirit.Audit/README.md)
346- 控制器规范: [controller.mdc](mdc:.cursor/rules/controller.mdc)
347 

Sections

  • 安全规范
  • 权限系统架构
  • 权限代码格式
  • PermissionAttribute 特性
  • 权限继承机制
  • IHasPermissionService
  • 审计实体
  • AuditableEntityBase
  • 实体审计接口
  • 多租户数据隔离
  • IMultiTenant 接口
  • 租户过滤行为
  • 数据保护
  • 排除敏感字段
  • 密码安全存储
  • SQL 注入防护
  • 日志安全
  • 敏感信息脱敏
  • 异常日志处理
  • CORS 配置
  • CSRF/XSS 防护
  • 安全配置
  • JWT 配置
  • 审计配置
  • 禁止事项
  • 安全检查清单
  • 参考文件

What it covers

database

Stack — with the evidence

csharp

(1.00)

react

(0.70)

typescript

(0.60)

dotnet

(0.60)

kubernetes

(0.60)

github-actions

(0.60)

javascript

(0.50)

Glob targeting

  • **/Entities/**/*.cs
  • **/*Entity*.cs
  • **/Authorization/**/*.cs
  • *Service*.cs

Format

Cursor rules

The most expressive format here. Many small .mdc files, each with frontmatter declaring when it should load, so a rule about migrations only enters context when a migration is open. Costs the most to maintain and only one editor reads it.

What the corpus says about it

Repository

Owner
xin-lai
Language
—
License
—
Archived
no

All configs in this repo

Also in xin-lai/CodeSpirit

Diff this repo’s formats

One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?

The other instruction files in this repository
RepositoryFormatStackCoversScoreChanged
xin-lai/CodeSpirit.cursor/rules/js.mdc · 56Cursor rulescsharpreact+5apidocs46/1003 days ago
xin-lai/CodeSpirit.cursor/rules/ai-development.mdc · 56Cursor rulescsharpreact+5api46/1003 days ago
xin-lai/CodeSpirit.cursor/rules/all.mdc · 56Cursor rulescsharpreact+5testing-strategyapi50/1003 days ago
xin-lai/CodeSpirit.cursor/rules/amis-cards.mdc · 56Cursor rulescsharpreact+5no sections54/1003 days ago
xin-lai/CodeSpirit.cursor/rules/api-design.mdc · 56Cursor rulescsharpreact+5no sections54/1003 days ago
xin-lai/CodeSpirit.cursor/rules/controller.mdc · 56Cursor rulescsharpreact+5api54/1003 days ago
xin-lai/CodeSpirit.cursor/rules/cs.mdc · 56Cursor rulescsharpreact+5no sections25/1003 days ago
xin-lai/CodeSpirit.cursor/rules/csproj.mdc · 56Cursor rulescsharpreact+5api54/1003 days ago
xin-lai/CodeSpirit.cursor/rules/css.mdc · 56Cursor rulescsharpreact+5ui54/1003 days ago
xin-lai/CodeSpirit.cursor/rules/database.mdc · 56Cursor rulescsharpreact+5no sections74/1003 days ago
xin-lai/CodeSpirit.cursor/rules/dependency-injection.mdc · 56Cursor rulescsharpreact+5api54/1003 days ago
xin-lai/CodeSpirit.cursor/rules/dto.mdc · 56Cursor rulescsharpreact+5no sections50/1003 days ago
xin-lai/CodeSpirit.cursor/rules/enum.mdc · 56Cursor rulescsharpreact+5no sections50/1003 days ago
xin-lai/CodeSpirit.cursor/rules/i18n.mdc · 56Cursor rulescsharpreact+5no sections50/1003 days ago
xin-lai/CodeSpirit.cursor/rules/naming-conventions.mdc · 56Cursor rulescsharpreact+5no sections50/1003 days ago
xin-lai/CodeSpirit.cursor/rules/package-management.mdc · 56Cursor rulescsharpreact+5no sections74/1003 days ago
xin-lai/CodeSpirit.cursor/rules/performance.mdc · 56Cursor rulescsharpreact+5no sections54/1003 days ago
xin-lai/CodeSpirit.cursor/rules/project-structure.mdc · 56Cursor rulescsharpreact+5api54/1003 days ago
xin-lai/CodeSpirit.cursor/rules/service.mdc · 56Cursor rulescsharpreact+5no sections50/1003 days ago
xin-lai/CodeSpirit.cursor/rules/startup-framework.mdc · 56Cursor rulescsharpreact+5api54/1003 days ago
Diff against .cursor/rules/js.mdc Diff against .cursor/rules/ai-development.mdc Diff against .cursor/rules/all.mdc Diff against .cursor/rules/amis-cards.mdc Diff against .cursor/rules/api-design.mdc Diff against .cursor/rules/controller.mdc Diff against .cursor/rules/cs.mdc Diff against .cursor/rules/csproj.mdc Diff against .cursor/rules/css.mdc Diff against .cursor/rules/database.mdc Diff against .cursor/rules/dependency-injection.mdc Diff against .cursor/rules/dto.mdc Diff against .cursor/rules/enum.mdc Diff against .cursor/rules/i18n.mdc Diff against .cursor/rules/naming-conventions.mdc Diff against .cursor/rules/package-management.mdc Diff against .cursor/rules/performance.mdc Diff against .cursor/rules/project-structure.mdc Diff against .cursor/rules/service.mdc Diff against .cursor/rules/startup-framework.mdc

Similar configs

Same format, overlapping stack, ranked by quality.

Same format, overlapping stack, ranked by quality
RepositoryFormatStackCoversScoreChanged
hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126Cursor rulesgobun+5setupbuildtestlint-format+6100/1003 days ago
TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 45Cursor rulestypescriptpytest+15testlint-formatstylearch+5100/1003 days ago
markstev/mark-starter.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+14setuptestlint-formatstyle+699/1003 days ago
Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+13setuptestlint-formatstyle+799/1003 days ago
deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1Cursor rulestypescriptnextjs+5setuptestlint-formatstyle+799/1003 days ago
dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+15setuptestlint-formatstyle+799/1003 days ago
langflow-ai/langflow.cursor/rules/docs_development.mdc · 153kCursor rulespythonnode+16setupbuildtestlint-format+797/1003 days ago
TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 45Cursor rulestypescriptpytest+15teststyletesting-strategysecurity+397/1003 days ago
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack