当前位置:首页 > 技术 > 正文内容

ASP.NET Core 路由参数加密:使用 IDataProtector 隐藏真实 ID

访客 技术 2026年6月23日 1

背景与安全隐患

在 Web 应用程序中,直接在 URL 中暴露数据库的主键 ID(例如 /student/details/1)是一种常见做法。然而,这种方式存在明显的安全隐患:攻击者可以通过递增或递减 ID 来遍历系统数据,甚至猜测出敏感资源的地址。为了防止这种不安全的直接对象引用(IDOR),我们可以对 URL 中的路由参数进行加密混淆。

使用 Data Protection API

ASP.NET Core 提供了内置的 Microsoft.AspNetCore.DataProtection 命名空间,其中的 IDataProtector 接口可以轻松实现数据的加密与解密。它会自动管理加密密钥的轮换和存储,非常适合用于处理 URL 参数、Cookie 等短生命周期或需要防篡改的数据。

1. 定义加密用途(Purpose)

在数据保护 API 中,"Purpose" 字符串用于隔离不同的加密上下文。即使使用相同的密钥,不同的 Purpose 也会生成完全不同的密文。我们首先定义一个类来集中管理这些用途字符串。

public sealed class RouteProtectionPurposes
{
    public const string StudentProfileId = "StudentProfile.Route.Id";
    public const string OrderTrackingId = "OrderTracking.Route.Id";
    public const string ArticleSlug = "Article.Route.Slug";
}

2. 注册服务

Program.cs 中,将用途常量类注册到依赖注入容器中。通常,调用 AddControllersWithViews()AddRazorPages() 时,数据保护服务已经默认注册。如果没有,可以显式调用 AddDataProtection()

var builder = WebApplication.CreateBuilder(args);

// 确保数据保护服务已注册
builder.Services.AddDataProtection();

// 注册用途常量类
builder.Services.AddSingleton<RouteProtectionPurposes>();

// 注册其他业务服务
builder.Services.AddScoped<IStudentService, StudentService>();

3. 在控制器中加密路由参数

在生成列表页面时,我们需要将实体的真实 ID 转换为加密字符串,并将其传递给视图以生成安全的 URL 链接。

public class StudentController : Controller
{
    private readonly IDataProtector _protector;
    private readonly IStudentService _studentService;

    public StudentController(
        IDataProtectionProvider protectionProvider, 
        RouteProtectionPurposes purposes, 
        IStudentService studentService)
    {
        // 使用特定的 Purpose 创建保护器实例
        _protector = protectionProvider.CreateProtector(purposes.StudentProfileId);
        _studentService = studentService;
    }

    [HttpGet]
    public async Task<IActionResult> Index()
    {
        var students = await _studentService.GetAllStudentsAsync();
        
        // 将真实 ID 加密并映射到视图模型
        var viewModels = students.Select(s => new StudentListItemViewModel
        {
            FullName = s.FullName,
            SecureId = _protector.Protect(s.Id.ToString())
        }).ToList();

        return View(viewModels);
    }
}

在 Razor 视图中,可以使用 SecureId 来构建链接:

<a asp-action="Details" asp-route-secureId="@model.SecureId">查看详情</a>

4. 接收请求并解密参数

当用户点击链接访问详情页时,控制器需要接收加密的字符串,尝试解密,并处理可能出现的篡改异常。

public class StudentController : Controller
{
    // ... 构造函数与字段同上 ...

    [HttpGet("student/details/{secureId}")]
    public async Task<IActionResult> Details(string secureId)
    {
        if (string.IsNullOrWhiteSpace(secureId))
        {
            return NotFound();
        }

        int realId;
        try
        {
            // 尝试解密密文
            var decryptedValue = _protector.Unprotect(secureId);
            realId = int.Parse(decryptedValue);
        }
        catch (CryptographicException)
        {
            // 捕获加密异常:密文被篡改、密钥不匹配或已过期
            return BadRequest("The provided identifier is invalid or has been tampered with.");
        }
        catch (FormatException)
        {
            // 捕获格式异常:解密后的字符串不是有效的整数
            return BadRequest("Invalid identifier format.");
        }

        var student = await _studentService.GetStudentByIdAsync(realId);
        if (student == null)
        {
            return NotFound();
        }

        return View(student);
    }
}

核心优势

通过上述实现,URL 中的 ID 变为了类似 /student/details/CfDJ8...(一长串Base64字符) 的格式。这不仅彻底杜绝了用户通过猜测 ID 遍历数据的可能,还自带了防篡改校验(如果用户修改了密文中的任何一个字符,Unprotect 方法都会抛出 CryptographicException)。相比于自行实现 AES 加密或引入第三方库,使用原生的 Data Protection API 更加轻量、安全且易于维护。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。