VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > c#编程 >
  • 特性应用——C#演示API接口权限标记

第一部分:C#基础入门
实例10:特性应用——API接口权限标记
实例介绍
在后端API开发中,权限验证是核心安全需求:不同用户(如管理员、普通用户)能访问的接口不同。传统的权限验证需要在每个接口里写重复的检查逻辑,而特性(Attribute)可以将权限规则“标记”在接口方法上,再通过反射在运行时统一验证,实现代码解耦。
特性是.NET中给代码元素(类、方法、属性等)添加元数据的机制——元数据是描述代码的数据,程序可以通过反射读取这些元数据并做出相应处理。本实例通过自定义权限特性,标记API接口的权限要求,再用反射实现
vb.net教程C#教程python教程SQL教程access 2010教程
统一权限验证,带你掌握特性的定义、使用和运行时处理全流程。
需求分析
1.定义权限特性:PermissionAttribute,用于标记API方法需要的权限(如Admin、User);
2.模拟API控制器:UserController,包含多个接口方法,用特性标记不同权限要求;
3.权限验证工具:PermissionValidator,通过反射读取方法上的特性,验证用户是否有权限访问;
4.测试场景:
1.管理员用户访问所有接口;
2.普通用户访问标记User权限的接口;
3.无权限用户访问受限接口被拒绝;
5.异常处理:处理方法未标记特性的情况(默认允许/拒绝)。
代码实现
csharp

	using System;
	using System.Reflection;
	
	namespace AttributePermissionDemo
	{
	// ==================== 1. 自定义权限特性 ====================
	/// <summary>
	/// API接口权限标记特性
	/// </summary>
	[AttributeUsage(AttributeTargets.Method, // 特性可应用于方法
	AllowMultiple = false, // 是否允许一个方法标记多个该特性(false=不允许)
	Inherited = false)] // 子类是否继承父类方法上的特性(false=不继承)
	public class PermissionAttribute : Attribute
	{
	/// <summary>
	/// 所需权限名称
	/// </summary>
	public string RequiredPermission { get; }
	
	/// <summary>
	/// 构造函数:传入所需权限
	/// </summary>
	/// <param name="requiredPermission">权限名称(如Admin、User)</param>
	public PermissionAttribute(string requiredPermission)
	{
	RequiredPermission = requiredPermission;
	}
	}
	
	// ==================== 2. 模拟API控制器 ====================
	/// <summary>
	/// 用户管理API控制器
	/// </summary>
	public class UserController
	{
	/// <summary>
	/// 获取所有用户(需要Admin权限)
	/// </summary>
	[Permission("Admin")]
	public void GetAllUsers()
	{
	Console.WriteLine("✅ 成功获取所有用户数据");
	}
	
	/// <summary>
	/// 获取当前用户信息(需要User权限)
	/// </summary>
	[Permission("User")]
	public void GetCurrentUser()
	{
	Console.WriteLine("✅ 成功获取当前用户信息");
	}
	
	/// <summary>
	/// 公开接口(无需权限)
	/// </summary>
	public void PublicInfo()
	{
	Console.WriteLine("✅ 公开信息:欢迎访问系统");
	}
	}
	
	// ==================== 3. 权限验证工具类 ====================
	/// <summary>
	/// 权限验证工具
	/// </summary>
	public static class PermissionValidator
	{
	/// <summary>
	/// 验证用户是否有权限访问指定方法
	/// </summary>
	/// <param name="controller">API控制器实例</param>
	/// <param name="methodName">方法名称</param>
	/// <param name="userPermissions">用户拥有的权限列表</param>
	/// <returns>是否有权限</returns>
	public static bool Validate(object controller, string methodName, string[] userPermissions)
	{
	// 1. 获取方法的Type对象
	Type controllerType = controller.GetType();
	MethodInfo methodInfo = controllerType.GetMethod(methodName);
	if (methodInfo == null)
	{
	Console.WriteLine($"❌ 方法{methodName}不存在");
	return false;
	}
	
	// 2. 读取方法上的PermissionAttribute特性
	PermissionAttribute permissionAttr = methodInfo.GetCustomAttribute<PermissionAttribute>();
	if (permissionAttr == null)
	{
	// 无特性标记:默认允许访问(可根据业务调整为拒绝)
	return true;
	}
	
	// 3. 检查用户是否拥有所需权限
	string requiredPermission = permissionAttr.RequiredPermission;
	bool hasPermission = Array.Exists(userPermissions, p => p.Equals(requiredPermission, StringComparison.OrdinalIgnoreCase));
	
	if (!hasPermission)
	{
	Console.WriteLine($"❌ 无权限访问:需要{requiredPermission}权限");
	}
	return hasPermission;
	}
	}
	
	// ==================== 4. 测试程序 ====================
	class Program
	{
	static void Main(string[] args)
	{
	UserController api = new UserController();
	
	// 模拟不同权限的用户
	string[] adminPermissions = new[] { "Admin", "User" };
	string[] userPermissions = new[] { "User" };
	string[] guestPermissions = new string[0];
	
	Console.WriteLine("=== 管理员用户访问 ===");
	TestAccess(api, "GetAllUsers", adminPermissions);
	TestAccess(api, "GetCurrentUser", adminPermissions);
	TestAccess(api, "PublicInfo", adminPermissions);
	
	Console.WriteLine("
=== 普通用户访问 ===");
	TestAccess(api, "GetAllUsers", userPermissions);
	TestAccess(api, "GetCurrentUser", userPermissions);
	TestAccess(api, "PublicInfo", userPermissions);
	
	Console.WriteLine("
=== 游客访问 ===");
	TestAccess(api, "GetAllUsers", guestPermissions);
	TestAccess(api, "GetCurrentUser", guestPermissions);
	TestAccess(api, "PublicInfo", guestPermissions);
	}
	
	/// <summary>
	/// 测试用户访问指定方法
	/// </summary>
	static void TestAccess(UserController api, string methodName, string[] permissions)
	{
	Console.Write($"访问{methodName}:");
	if (PermissionValidator.Validate(api, methodName, permissions))
	{
	// 反射调用方法(实际项目中可能通过HTTP请求触发)
	MethodInfo method = typeof(UserController).GetMethod(methodName);
	method?.Invoke(api, null);
	}
	}
	}
	}
逐行讲解
1. 自定义权限特性(PermissionAttribute)
csharp 
	[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
	public class PermissionAttribute : Attribute
	{
	public string RequiredPermission { get; }
	public PermissionAttribute(string requiredPermission)
	{
	RequiredPermission = requiredPermission;
	}
	}

继承Attribute:所有自定义特性必须直接或间接继承自System.Attribute,这是.NET的约定;
AttributeUsage特性:标记当前特性的使用规则:
AttributeTargets.Method:只能应用于方法(还可指定类、属性等,AttributeTargets.Class | AttributeTargets.Method);
AllowMultiple=false:一个方法只能标记一次该特性(若需多个权限,可设为true并存储权限列表);
Inherited=false:子类方法不会继承父类方法的特性(如父类方法标记了Admin权限,子类重写该方法不会自动继承);
构造函数:特性的构造函数用于接收参数(如权限名称),参数会存储为特性的属性,供运行时读取。
2. API方法标记特性
csharp

	[Permission("Admin")]
	public void GetAllUsers() { ... }

用[Permission("Admin")]标记方法需要Admin权限,编译器会将该特性的元数据存储到程序集中;
无特性标记的方法(如PublicInfo),验证工具会默认允许访问(可根据业务调整逻辑)。
3. 权限验证工具类(PermissionValidator)
核心逻辑在Validate方法:
获取方法Type:通过controller.GetType()和GetMethod(methodName)获取方法的反射对象MethodInfo;
读取特性:methodInfo.GetCustomAttribute()读取方法上的特性(若没有则返回null);
权限检查:对比用户权限列表和特性中的RequiredPermission,判断是否允许访问。
4. 测试程序
模拟不同权限的用户访问API方法:
管理员:能访问所有方法;
普通用户:无法访问GetAllUsers(需要Admin权限);
游客:只能访问无特性标记的PublicInfo方法。
基础知识拓展

  1. 特性的本质与分类
    本质:特性是存储在程序集元数据中的“标签”,本身不执行任何代码,需要通过反射读取并处理;
    分类:
    预定义特性:.NET内置的特性,如[Obsolete](标记过时方法)、[Serializable](标记可序列化类)、[DataContract](WCF序列化);
    自定义特性:像实例中的PermissionAttribute,根据业务需求自定义元数据标记。
  2. 特性的常见应用场景
    权限验证:如实例中的API权限标记;
    序列化控制:[JsonProperty](Newtonsoft.Json)标记JSON字段名,[IgnoreDataMember]标记忽略序列化的属性;
    ORM映射:[Table](EF Core)标记数据库表名,[Column]标记列名;
    单元测试:[Test](NUnit)标记测试方法,[TestCase]标记测试参数;
    AOP拦截:结合AOP框架(如AspectCore、Autofac),用特性标记需要拦截的方法(如日志、事务)。
  3. 特性vs注释vs配置文件
技术 作用对象 可读性 程序可访问性 适用场景
特性 代码元素 中等(需反射) 是 程序运行时需要读取的元数据
注释 代码(给人看) 高 否 代码说明、文档生成
配置文件 应用程序 高 是 动态调整的参数(如数据库连接)
  1. 特性的性能考量
    反射开销:读取特性需要反射,反射比直接调用慢,但在API权限验证场景中,一次请求只反射一次方法,开销可忽略;
    优化方案:缓存反射结果(如将方法→权限的映射缓存到字典中),避免重复反射同一方法。
    扩展思考

多权限支持:如何让一个方法需要多个权限(如同时需要Admin和User)?

修改PermissionAttribute的AllowMultiple=true,并在验证时检查用户是否拥有所有所需权限;
示例:[Permission("Admin")][Permission("User")]标记方法,验证时需同时满足两个权限。

全局权限拦截:在ASP.NET Core中,如何用特性实现全局权限拦截?

编写中间件或Action过滤器(IActionFilter),在请求到达控制器前,通过反射读取Action方法上的特性,验证权限;
示例:[PermissionFilter]标记控制器,过滤器在OnActionExecuting中执行权限验证。

特性的高级用法:如何让特性支持参数化配置(如权限过期时间)?

在特性中添加属性(如public DateTime ExpireTime { get; set; }),标记方法时传入参数:[Permission("Admin", ExpireTime = "2025-12-31")];
验证时读取ExpireTime,判断权限是否过期。
总结
特性是.NET中元编程的核心技术,通过给代码添加元数据,实现了“标记-处理”的解耦模式。在API权限场景中,特性让权限规则与业务逻辑分离,统一验证逻辑,减少重复代码。
掌握特性的关键是理解:特性本身不执行代码,只是存储信息,需要反射或框架(如ASP.NET Core过滤器)来处理这些信息。合理使用特性可以让代码更简洁、更易维护,是后端开发必备技能之一。

本站原创,转载请注明出处:https://www.xin3721.com/ArticlecSharp/c49412.html


相关教程