Token导航 LogoToken导航

Agent Skill · 待分类

permission-authorization(权限授权)

用于辅助安全审计、权限检查、凭据风险、认证流程和常见漏洞排查。它适合让 Agent 梳理敏感配置、检查依赖风险、分析鉴权逻辑或生成安全复核清单。使用时不能把工具输出直接当最终结论,涉及密钥、令牌、用户数据或生产系统时,应先确认最小权限、脱敏方式和操作边界。

permission-authorization 是待分类类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为只读;许可证信息还不明确,第三方扫描已通过,按安装量在待分类类的 11,209 个 Skill 里排第 9,557。

总安装 238周安装 10GitHub Stars 50下载 83核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:permission-authorization(权限授权)
来源仓库:https://github.com/ronnythedev/dotnet-clean-architecture-skills
仓库路径:skills/permission-authorization
安装命令:
npx skills add https://github.com/ronnythedev/dotnet-clean-architecture-skills --skill permission-authorization
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/ronnythedev/dotnet-clean-architecture-skills --skill permission-authorization

这个 Skill 是做什么的

这个 Skill 的分类还没最终确定,用法以来源仓库的说明为准。

用于辅助安全审计、权限检查、凭据风险、认证流程和常见漏洞排查。它适合让 Agent 梳理敏感配置、检查依赖风险、分析鉴权逻辑或生成安全复核清单。使用时不能把工具输出直接当最终结论,涉及密钥、令牌、用户数据或生产系统时,应先确认最小权限、脱敏方式和操作边界。它属于待分类工具,适用于安全审计场景。

permission-authorization 属于待分类类 Skill,可作为该场景下的辅助能力补充。

来源仓库内路径:skills/permission-authorization

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/ronnythedev/dotnet-clean-architecture-skills -…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它标注为只读,先用只读任务试一次,确认行为符合预期再扩大使用范围。

常见问题

6 条

permission-authorization 怎么安装?

在终端执行 npx skills add https://github.com/ronnythedev/dotnet-clean-architecture-skills --skill per…。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

permission-authorization 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

permission-authorization 需要什么权限?

权限级别是只读。该 Skill 主要提供规则、说明或参考内容,本身偏只读;真正读写文件、联网或执行命令仍取决于宿主 Agent 的任务。

permission-authorization 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

permission-authorization 用的人多吗?

公开数据是累计安装 238 次,近一周安装 10 次,下载 83 次,GitHub 50 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

permission-authorization 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。
  • 标注为只读权限,试用阶段不容易误改本地文件。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理待分类类任务、又不想每次都手写提示词的人。
  • 只想先试试效果、不希望它改动本地文件的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

待分类类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
infsh-cli

infsh CLI · Codex、Claude

4,374,576382权限未标注未明确未收录
ai-video-generation

AI 视频生成 · Codex、Claude

4,313,376382调用外部服务未明确有提醒
lark-openapi-explorer

云雀 OpenAPI 浏览器 · Codex、Claude

2,064,1209,011需要联网未明确有提醒
lark-workflow-standup-report

Lark 工作流程站立报告 · Codex、Claude

2,041,6328,978需要联网未明确通过
use-my-browser

使用我的浏览器 · Codex、Claude

1,848,49140操作浏览器未明确未通过
permission-authorization

权限授权 · 本页

23850只读未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Permission-Based Authorization Setup

Overview

This skill implements fine-grained permission-based authorization:

  • Custom [HasPermission] attribute - Declarative permission requirements
  • Policy provider - Dynamically creates policies from permissions
  • Authorization handler - Validates user permissions
  • Claims transformation - Converts roles to permissions

Quick Reference

ComponentPurpose
PermissionsStatic permission constants
RolesStatic role constants
HasPermissionAttributeCustom authorize attribute
PermissionAuthorizationHandlerValidates permissions
PermissionAuthorizationPolicyProviderCreates policies dynamically
RoleToPermissionClaimsTransformationMaps roles to permissions

Authorization Structure

/Infrastructure/Authorization/
├── Permissions.cs
├── Roles.cs
├── HasPermissionAttribute.cs
├── PermissionRequirement.cs
├── PermissionAuthorizationHandler.cs
├── PermissionAuthorizationPolicyProvider.cs
├── RoleToPermissionClaimsTransformation.cs
└── AuthorizationExtensions.cs

Template: Permissions Definition

// src/{name}.infrastructure/Authorization/Permissions.cs
namespace {name}.infrastructure.authorization;

/// <summary>
/// All available permissions in the system
/// Format: {resource}:{action}
/// </summary>
public static class Permissions
{
    // ═══════════════════════════════════════════════════════════════
    // ORGANIZATION PERMISSIONS
    // ═══════════════════════════════════════════════════════════════
    public const string OrganizationsRead = "organizations:read";
    public const string OrganizationsWrite = "organizations:write";
    public const string OrganizationsDelete = "organizations:delete";
    public const string OrganizationsManageSettings = "organizations:manage_settings";

    // ═══════════════════════════════════════════════════════════════
    // USER PERMISSIONS
    // ═══════════════════════════════════════════════════════════════
    public const string UsersRead = "users:read";
    public const string UsersWrite = "users:write";
    public const string UsersDelete = "users:delete";
    public const string UsersManageRoles = "users:manage_roles";

    // ═══════════════════════════════════════════════════════════════
    // DEPARTMENT PERMISSIONS
    // ═══════════════════════════════════════════════════════════════
    public const string DepartmentsRead = "departments:read";
    public const string DepartmentsWrite = "departments:write";
    public const string DepartmentsDelete = "departments:delete";

    // ═══════════════════════════════════════════════════════════════
    // ASSESSMENT PERMISSIONS
    // ═══════════════════════════════════════════════════════════════
    public const string AssessmentsRead = "assessments:read";
    public const string AssessmentsWrite = "assessments:write";
    public const string AssessmentsSubmit = "assessments:submit";
    public const string AssessmentsReview = "assessments:review";

    // ═══════════════════════════════════════════════════════════════
    // REPORT PERMISSIONS
    // ═══════════════════════════════════════════════════════════════
    public const string ReportsRead = "reports:read";
    public const string ReportsExport = "reports:export";
    public const string ReportsViewSensitive = "reports:view_sensitive";

    // ═══════════════════════════════════════════════════════════════
    // ADMIN PERMISSIONS
    // ═══════════════════════════════════════════════════════════════
    public const string AdminAccess = "admin:access";
    public const string AdminManageSystem = "admin:manage_system";
}

Template: Roles Definition

// src/{name}.infrastructure/Authorization/Roles.cs
namespace {name}.infrastructure.authorization;

/// <summary>
/// All available roles in the system
/// </summary>
public static class Roles
{
    public const string SuperAdmin = "SuperAdmin";
    public const string Admin = "Admin";
    public const string Consultant = "Consultant";
    public const string Manager = "Manager";
    public const string Associate = "Associate";
    public const string Viewer = "Viewer";
}

Template: Role-Permission Mapping

// src/{name}.infrastructure/Authorization/RolePermissions.cs
namespace {name}.infrastructure.authorization;

/// <summary>
/// Maps roles to their granted permissions
/// </summary>
public static class RolePermissions
{
    private static readonly Dictionary<string, HashSet<string>> RolePermissionMap = new()
    {
        // ═══════════════════════════════════════════════════════════════
        // SUPER ADMIN - Full system access
        // ═══════════════════════════════════════════════════════════════
        [Roles.SuperAdmin] = new HashSet<string>
        {
            Permissions.OrganizationsRead,
            Permissions.OrganizationsWrite,
            Permissions.OrganizationsDelete,
            Permissions.OrganizationsManageSettings,
            Permissions.UsersRead,
            Permissions.UsersWrite,
            Permissions.UsersDelete,
            Permissions.UsersManageRoles,
            Permissions.DepartmentsRead,
            Permissions.DepartmentsWrite,
            Permissions.DepartmentsDelete,
            Permissions.AssessmentsRead,
            Permissions.AssessmentsWrite,
            Permissions.AssessmentsSubmit,
            Permissions.AssessmentsReview,
            Permissions.ReportsRead,
            Permissions.ReportsExport,
            Permissions.ReportsViewSensitive,
            Permissions.AdminAccess,
            Permissions.AdminManageSystem
        },

        // ═══════════════════════════════════════════════════════════════
        // ADMIN - Organization-level admin
        // ═══════════════════════════════════════════════════════════════
        [Roles.Admin] = new HashSet<string>
        {
            Permissions.OrganizationsRead,
            Permissions.OrganizationsWrite,
            Permissions.OrganizationsManageSettings,
            Permissions.UsersRead,
            Permissions.UsersWrite,
            Permissions.UsersManageRoles,
            Permissions.DepartmentsRead,
            Permissions.DepartmentsWrite,
            Permissions.DepartmentsDelete,
            Permissions.AssessmentsRead,
            Permissions.AssessmentsWrite,
            Permissions.AssessmentsReview,
            Permissions.ReportsRead,
            Permissions.ReportsExport,
            Permissions.ReportsViewSensitive,
            Permissions.AdminAccess
        },

        // ═══════════════════════════════════════════════════════════════
        // CONSULTANT - External consultants
        // ═══════════════════════════════════════════════════════════════
        [Roles.Consultant] = new HashSet<string>
        {
            Permissions.OrganizationsRead,
            Permissions.UsersRead,
            Permissions.DepartmentsRead,
            Permissions.AssessmentsRead,
            Permissions.AssessmentsReview,
            Permissions.ReportsRead,
            Permissions.ReportsExport
        },

        // ═══════════════════════════════════════════════════════════════
        // MANAGER - Department managers
        // ═══════════════════════════════════════════════════════════════
        [Roles.Manager] = new HashSet<string>
        {
            Permissions.OrganizationsRead,
            Permissions.UsersRead,
            Permissions.DepartmentsRead,
            Permissions.DepartmentsWrite,
            Permissions.AssessmentsRead,
            Permissions.AssessmentsWrite,
            Permissions.AssessmentsSubmit,
            Permissions.AssessmentsReview,
            Permissions.ReportsRead
        },

        // ═══════════════════════════════════════════════════════════════
        // ASSOCIATE - Regular employees
        // ═══════════════════════════════════════════════════════════════
        [Roles.Associate] = new HashSet<string>
        {
            Permissions.OrganizationsRead,
            Permissions.UsersRead,
            Permissions.DepartmentsRead,
            Permissions.AssessmentsRead,
            Permissions.AssessmentsSubmit
        },

        // ═══════════════════════════════════════════════════════════════
        // VIEWER - Read-only access
        // ═══════════════════════════════════════════════════════════════
        [Roles.Viewer] = new HashSet<string>
        {
            Permissions.OrganizationsRead,
            Permissions.DepartmentsRead,
            Permissions.AssessmentsRead,
            Permissions.ReportsRead
        }
    };

    /// <summary>
    /// Gets all permissions for a role
    /// </summary>
    public static IReadOnlySet<string> GetPermissionsForRole(string role)
    {
        return RolePermissionMap.TryGetValue(role, out var permissions)
            ? permissions
            : new HashSet<string>();
    }

    /// <summary>
    /// Gets all permissions for multiple roles
    /// </summary>
    public static IReadOnlySet<string> GetPermissionsForRoles(IEnumerable<string> roles)
    {
        var allPermissions = new HashSet<string>();

        foreach (var role in roles)
        {
            var permissions = GetPermissionsForRole(role);
            allPermissions.UnionWith(permissions);
        }

        return allPermissions;
    }

    /// <summary>
    /// Checks if a role has a specific permission
    /// </summary>
    public static bool HasPermission(string role, string permission)
    {
        return RolePermissionMap.TryGetValue(role, out var permissions)
            && permissions.Contains(permission);
    }
}

Template: HasPermission Attribute

// src/{name}.infrastructure/Authorization/HasPermissionAttribute.cs
using Microsoft.AspNetCore.Authorization;

namespace {name}.infrastructure.authorization;

/// <summary>
/// Custom authorization attribute that requires a specific permission
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public sealed class HasPermissionAttribute : AuthorizeAttribute
{
    public HasPermissionAttribute(string permission)
        : base(policy: permission)
    {
    }
}

Template: Permission Requirement

// src/{name}.infrastructure/Authorization/PermissionRequirement.cs
using Microsoft.AspNetCore.Authorization;

namespace {name}.infrastructure.authorization;

/// <summary>
/// Authorization requirement for a specific permission
/// </summary>
public sealed class PermissionRequirement : IAuthorizationRequirement
{
    public string Permission { get; }

    public PermissionRequirement(string permission)
    {
        Permission = permission;
    }
}

Template: Permission Authorization Handler

// src/{name}.infrastructure/Authorization/PermissionAuthorizationHandler.cs
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;

namespace {name}.infrastructure.authorization;

/// <summary>
/// Handles permission-based authorization requirements
/// </summary>
internal sealed class PermissionAuthorizationHandler
    : AuthorizationHandler<PermissionRequirement>
{
    private readonly ILogger<PermissionAuthorizationHandler> _logger;

    public PermissionAuthorizationHandler(
        ILogger<PermissionAuthorizationHandler> logger)
    {
        _logger = logger;
    }

    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context,
        PermissionRequirement requirement)
    {
        // Get permissions from claims (added by claims transformation)
        var permissions = context.User
            .FindAll("permission")
            .Select(c => c.Value)
            .ToHashSet();

        if (permissions.Contains(requirement.Permission))
        {
            _logger.LogDebug(
                "User {UserId} authorized for permission {Permission}",
                context.User.FindFirst(ClaimTypes.NameIdentifier)?.Value,
                requirement.Permission);

            context.Succeed(requirement);
        }
        else
        {
            _logger.LogWarning(
                "User {UserId} denied permission {Permission}. User has permissions: {Permissions}",
                context.User.FindFirst(ClaimTypes.NameIdentifier)?.Value,
                requirement.Permission,
                string.Join(", ", permissions));
        }

        return Task.CompletedTask;
    }
}

Template: Permission Policy Provider

// src/{name}.infrastructure/Authorization/PermissionAuthorizationPolicyProvider.cs
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;

namespace {name}.infrastructure.authorization;

/// <summary>
/// Dynamically creates authorization policies based on permission names
/// </summary>
internal sealed class PermissionAuthorizationPolicyProvider
    : DefaultAuthorizationPolicyProvider
{
    private readonly AuthorizationOptions _options;

    public PermissionAuthorizationPolicyProvider(
        IOptions<AuthorizationOptions> options)
        : base(options)
    {
        _options = options.Value;
    }

    public override async Task<AuthorizationPolicy?> GetPolicyAsync(string policyName)
    {
        // First check if policy exists in options
        var policy = await base.GetPolicyAsync(policyName);

        if (policy is not null)
        {
            return policy;
        }

        // If not found, create a permission-based policy
        // Policy name is the permission (e.g., "users:read")
        policy = new AuthorizationPolicyBuilder()
            .AddRequirements(new PermissionRequirement(policyName))
            .Build();

        // Cache the policy
        _options.AddPolicy(policyName, policy);

        return policy;
    }
}

Template: Claims Transformation

// src/{name}.infrastructure/Authorization/RoleToPermissionClaimsTransformation.cs
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;

namespace {name}.infrastructure.authorization;

/// <summary>
/// Transforms role claims into permission claims
/// </summary>
internal sealed class RoleToPermissionClaimsTransformation
    : IClaimsTransformation
{
    public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        // Get all role claims
        var roles = principal
            .FindAll(ClaimTypes.Role)
            .Select(c => c.Value)
            .ToList();

        if (!roles.Any())
        {
            return Task.FromResult(principal);
        }

        // Get permissions for all roles
        var permissions = RolePermissions.GetPermissionsForRoles(roles);

        // Create new identity with permission claims
        var identity = principal.Identity as ClaimsIdentity;

        if (identity is null)
        {
            return Task.FromResult(principal);
        }

        // Add permission claims (only if not already present)
        foreach (var permission in permissions)
        {
            if (!principal.HasClaim("permission", permission))
            {
                identity.AddClaim(new Claim("permission", permission));
            }
        }

        return Task.FromResult(principal);
    }
}

Template: Authorization Registration

// src/{name}.infrastructure/Authorization/AuthorizationExtensions.cs
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;

namespace {name}.infrastructure.authorization;

public static class AuthorizationExtensions
{
    public static IServiceCollection AddPermissionAuthorization(
        this IServiceCollection services)
    {
        // Register policy provider
        services.AddSingleton<IAuthorizationPolicyProvider,
            PermissionAuthorizationPolicyProvider>();

        // Register authorization handler
        services.AddScoped<IAuthorizationHandler,
            PermissionAuthorizationHandler>();

        // Register claims transformation
        services.AddScoped<IClaimsTransformation,
            RoleToPermissionClaimsTransformation>();

        // Configure authorization
        services.AddAuthorization(options =>
        {
            // Default policy requires authentication
            options.DefaultPolicy = new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .Build();

            // Fallback policy for endpoints without [Authorize]
            options.FallbackPolicy = null;  // Allow anonymous by default

            // Add named policies for common scenarios
            options.AddPolicy("AdminOnly", policy =>
                policy.RequireRole(Roles.SuperAdmin, Roles.Admin));

            options.AddPolicy("ManagerOrAbove", policy =>
                policy.RequireRole(Roles.SuperAdmin, Roles.Admin, Roles.Manager));
        });

        return services;
    }
}

Usage in Controllers

// src/{name}.api/Controllers/Users/UserController.cs
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using {name}.infrastructure.authorization;

[Authorize]  // Requires authentication
[ApiController]
[Route("api/v1/users")]
public class UserController : ControllerBase
{
    // ═══════════════════════════════════════════════════════════════
    // PUBLIC: Any authenticated user
    // ═══════════════════════════════════════════════════════════════
    [HttpGet("{id}")]
    [HasPermission(Permissions.UsersRead)]
    public async Task<IActionResult> GetById(Guid id) { }

    // ═══════════════════════════════════════════════════════════════
    // CREATE: Requires write permission
    // ═══════════════════════════════════════════════════════════════
    [HttpPost]
    [HasPermission(Permissions.UsersWrite)]
    public async Task<IActionResult> Create([FromBody] CreateUserRequest request) { }

    // ═══════════════════════════════════════════════════════════════
    // DELETE: Requires delete permission
    // ═══════════════════════════════════════════════════════════════
    [HttpDelete("{id}")]
    [HasPermission(Permissions.UsersDelete)]
    public async Task<IActionResult> Delete(Guid id) { }

    // ═══════════════════════════════════════════════════════════════
    // MULTIPLE PERMISSIONS: All required
    // ═══════════════════════════════════════════════════════════════
    [HttpPost("{id}/roles")]
    [HasPermission(Permissions.UsersWrite)]
    [HasPermission(Permissions.UsersManageRoles)]
    public async Task<IActionResult> AssignRole(Guid id, [FromBody] AssignRoleRequest request) { }

    // ═══════════════════════════════════════════════════════════════
    // ROLE-BASED: Use built-in attribute
    // ═══════════════════════════════════════════════════════════════
    [HttpGet("admin/dashboard")]
    [Authorize(Roles = Roles.SuperAdmin + "," + Roles.Admin)]
    public async Task<IActionResult> GetAdminDashboard() { }

    // ═══════════════════════════════════════════════════════════════
    // NAMED POLICY
    // ═══════════════════════════════════════════════════════════════
    [HttpDelete("organization/{orgId}")]
    [Authorize(Policy = "AdminOnly")]
    public async Task<IActionResult> DeleteOrganization(Guid orgId) { }
}

Usage in Handlers (Imperative)

// src/{name}.application/{Feature}/DoSomething/DoSomethingCommandHandler.cs
using Microsoft.AspNetCore.Authorization;
using {name}.application.abstractions.authentication;

internal sealed class DoSomethingCommandHandler
    : ICommandHandler<DoSomethingCommand, Guid>
{
    private readonly IUserContext _userContext;
    private readonly IAuthorizationService _authorizationService;

    public DoSomethingCommandHandler(
        IUserContext userContext,
        IAuthorizationService authorizationService)
    {
        _userContext = userContext;
        _authorizationService = authorizationService;
    }

    public async Task<Result<Guid>> Handle(
        DoSomethingCommand request,
        CancellationToken cancellationToken)
    {
        // Check permission imperatively
        var authResult = await _authorizationService.AuthorizeAsync(
            _userContext.User,
            Permissions.SomethingWrite);

        if (!authResult.Succeeded)
        {
            return Result.Failure<Guid>(CommonErrors.Forbidden);
        }

        // Continue with operation...
    }
}

Resource-Based Authorization

// src/{name}.infrastructure/Authorization/DocumentAuthorizationHandler.cs
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Infrastructure;

/// <summary>
/// Authorizes access to documents based on ownership
/// </summary>
internal sealed class DocumentAuthorizationHandler
    : AuthorizationHandler<OperationAuthorizationRequirement, Document>
{
    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context,
        OperationAuthorizationRequirement requirement,
        Document resource)
    {
        var userId = context.User.FindFirst("sub")?.Value;

        if (string.IsNullOrEmpty(userId))
        {
            return Task.CompletedTask;
        }

        // Owner can do anything
        if (resource.OwnerId.ToString() == userId)
        {
            context.Succeed(requirement);
            return Task.CompletedTask;
        }

        // Others need explicit permission based on operation
        if (requirement.Name == Operations.Read.Name)
        {
            if (context.User.HasClaim("permission", Permissions.DocumentsRead))
            {
                context.Succeed(requirement);
            }
        }

        return Task.CompletedTask;
    }
}

// Define operations
public static class Operations
{
    public static readonly OperationAuthorizationRequirement Create = new() { Name = "Create" };
    public static readonly OperationAuthorizationRequirement Read = new() { Name = "Read" };
    public static readonly OperationAuthorizationRequirement Update = new() { Name = "Update" };
    public static readonly OperationAuthorizationRequirement Delete = new() { Name = "Delete" };
}

Critical Rules

  1. Use constants for permissions - No magic strings
  2. Permission naming convention - {resource}:{action}
  3. Roles aggregate permissions - Don't check roles directly
  4. Claims transformation - Convert roles to permissions early
  5. Cache policies - Policy provider caches dynamically created policies
  6. Multiple attributes = AND - All permissions required
  7. Log authorization failures - For security auditing
  8. Don't trust client claims - Always validate on server
  9. Separate authn from authz - Authentication ≠ Authorization
  10. Resource-based when needed - For ownership checks

Anti-Patterns to Avoid

// ❌ WRONG: Checking roles directly in code
if (user.IsInRole("Admin") || user.IsInRole("Manager"))
{
    // This scatters role logic everywhere
}

// ✅ CORRECT: Check permission
[HasPermission(Permissions.UsersWrite)]
public async Task<IActionResult> CreateUser() { }

// ❌ WRONG: Magic strings for permissions
[Authorize(Policy = "users:write")]  // Typo risk!

// ✅ CORRECT: Use constants
[HasPermission(Permissions.UsersWrite)]

// ❌ WRONG: Trusting client-provided permissions
var permissions = request.UserPermissions;  // Client can't set permissions!

// ✅ CORRECT: Derive from authenticated roles
// Claims transformation handles this automatically

Related Skills

  • jwt-authentication - Authentication setup
  • api-controller-generator - Protected endpoints
  • dotnet-clean-architecture - Infrastructure layer

平台分布

Codex

37.45%
按下载量换算31

Claude

29.1%
按下载量换算24

Cursor

20.65%
按下载量换算17

Gemini CLI

10.26%
按下载量换算9

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

只读

该 Skill 主要提供规则、说明或参考内容,本身偏只读;真正读写文件、联网或执行命令仍取决于宿主 Agent 的任务。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills