导读:本期聚焦于Canve创作的《C#在ASP.NET Core中如何防止跨站脚本攻击?XSS防护方法详解》,敬请观看详情。跨站脚本攻击XSS是Web应用中最常见的安全漏洞之一,攻击者通过在页面中注入恶意脚本来窃取用户Cookie或执行非法操作。C#开发者在ASP.NET Core项目中有多种防护手段,比如使用HtmlEncoder对输出内容编码、开启Razor引擎的自动编码机制、配置Content-Security-Policy响应头、验证和过滤用户输入等。本文将系统讲解XSS的三种攻击类型及其原理,结合实际代码演示TagHelper的安全用法、编码器的自定义配置,以及如何通过CSP策略和Cookie安全属性构建多层防御体系,帮助你在项目中彻底堵住XSS漏洞。

跨站脚本攻击(XSS)一直是OWASP安全漏洞榜单上的常客,其核心问题在于:服务端把用户提交的数据原样输出到了HTML页面中,攻击者便可以借机注入一段恶意JavaScript,在所有访问该页面的用户浏览器中执行。C#开发者在ASP.NET Core中其实拥有相当完善的防护工具链,但很多人只知道Razor会自动编码,却不清楚哪些场景会绕过编码,最终留下安全缺口。本文从XSS原理讲起,逐层拆解ASP.NET Core中的防护手段。

C#在ASP.NET Core中如何防止跨站脚本攻击?XSS防护方法详解

理解XSS的攻击原理与三种类型

XSS的本质是数据与代码的边界被打破。当用户输入的内容未经处理就被拼进HTML,浏览器无法区分这是页面本身的脚本还是用户注入的脚本,于是照单全收地执行。比如一个留言板功能,如果直接把用户留言输出到页面,攻击者只需提交一段带有<script>标签的内容,就能让后续访问者的浏览器执行恶意代码。

XSS通常分为三类。第一类是反射型XSS,恶意脚本包含在URL参数中,服务端接收到请求后把参数直接回显到响应页面,典型场景是搜索结果页显示搜索关键词。第二类是存储型XSS,危害最大,攻击脚本被持久化保存到数据库,所有浏览相关页面的用户都会中招,比如评论区、个人签名等字段。第三类是DOM型XSS,服务端完全没有参与,是前端JavaScript在操作DOM时使用了不安全的方式,例如把location.hash直接赋值给innerHTML

针对前两类,防护重点在服务端的输出编码;针对DOM型XSS,则需要前端配合使用安全的API。C#开发者主要控制的是服务端这一层,这也是本文的重点。

HtmlEncoder输出编码:最基础也最核心的防线

输出编码的思路很简单:把HTML中的特殊字符转换成对应的实体。比如<会被编码成&lt;,这样浏览器就把它当作普通文本渲染,而不是标签的开始符号。ASP.NET Core提供了内置的HtmlEncoder类,可以直接注入使用。

public class CommentService
{
    private readonly HtmlEncoder _htmlEncoder;

    public CommentService(HtmlEncoder htmlEncoder)
    {
        _htmlEncoder = htmlEncoder;
    }

    public string Sanitize(string userContent)
    {
        // 将特殊字符编码为HTML实体,防止脚本被执行
        return _htmlEncoder.Encode(userContent);
    }
}

在Controller中手动拼接HTML时,务必使用编码器处理用户数据:

public IActionResult Search(string keyword)
{
    var encodedKeyword = HtmlEncoder.Default.Encode(keyword);
    var html = $"<p>您搜索的关键词是:{encodedKeyword}</p>";
    return Content(html, "text/html");
}

需要注意的是,编码必须发生在输出阶段,而不是输入阶段。有些项目习惯在保存数据时先编码一次,这个做法有隐患:数据可能被输出到不同上下文,比如JSON、URL、JavaScript变量,HTML编码并不适用于所有场景。正确的策略是存储原始数据,输出时按目标上下文选择对应的编码器,UrlEncoder处理URL场景,JavaScriptEncoder处理脚本场景。

Razor引擎的自动编码机制与危险写法

Razor是ASP.NET Core中最常用的视图引擎,它的默认行为是安全的:@Model.Name这样的语法会自动经过HTML编码。也就是说,大多数情况下开发者不需要额外做什么,输出就是安全的。真正危险的是那些绕过编码的写法。

第一个危险写法是Html.Raw。这个方法会原样输出内容,完全跳过编码,如果传入的值包含用户输入,就等于打开了XSS的大门。除非你确定内容来源可信,或者已经做过净化处理,否则不要使用它。第二个危险写法是HtmlStringMvcHtmlString,它们同样告诉Razor这段内容不需要编码。

<!-- 安全:自动编码 -->
<div>@Model.UserComment</div>

<!-- 危险:跳过编码,可能触发XSS -->
<div>@Html.Raw(Model.UserComment)</div>

<!-- 危险:属性值中使用Raw同样有风险 -->
<div data-content="@Html.Raw(Model.UserInput)">内容</div>

JavaScript上下文也需要特别注意。把用户数据嵌入到<script>块中时,HTML编码帮不上忙,因为脚本解析器不认识HTML实体。此时应使用JsonSerializer序列化,并配合JavaScriptEncoder

<script>
    // 使用Json序列化传递数据,避免字符串拼接
    var userConfig = @Html.Raw(JsonSerializer.Serialize(Model.Config, jsonOptions));
</script>

如果你需要在视图中允许部分HTML标签(比如富文本编辑器的内容),简单编码会让内容变成一堆实体字符串,此时需要引入HTML净化库,例如AngleSharp或HtmlSanitizer,只保留白名单内的标签和属性。

多层防御:CSP响应头与Cookie安全属性

输出编码是第一道防线,但成熟的安全方案讲究纵深防御。内容安全策略(CSP)是浏览器层面的强制约束,通过Content-Security-Policy响应头告诉浏览器只允许执行白名单内的脚本来源,即使攻击者成功注入了<script>标签,浏览器也会拒绝执行。

在ASP.NET Core中可以通过中间件统一添加CSP头:

public class CspMiddleware
{
    private readonly RequestDelegate _next;

    public CspMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        context.Response.Headers.Append(
            "Content-Security-Policy",
            "default-src 'self'; script-src 'self'; object-src 'none'");
        await _next(context);
    }
}

// 在Program.cs中注册
app.UseMiddleware<CspMiddleware>();

Cookie安全同样关键。XSS攻击的常见目标是窃取会话Cookie,将Cookie标记为HttpOnly后,JavaScript便无法通过document.cookie读取它:

builder.Services.ConfigureApplicationCookie(options =>
{
    options.Cookie.HttpOnly = true;   // 禁止JavaScript访问
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // 仅HTTPS传输
    options.Cookie.SameSite = SameSiteMode.Strict; // 防御CSRF
});

除了这些,还应在表单层面对输入做格式校验,使用ASP.NET Core的数据注解(如[RegularExpression])限制字段格式;对上传文件的扩展名和MIME类型严格白名单校验,防止把脚本文件当作图片输出。输入校验不能替代输出编码,但能显著缩小攻击面。

常见漏洞场景自查与总结

结合实际项目经验,有几个高频出错点值得自查。一是搜索页直接回显关键词,反射型XSS的典型入口;二是个人资料中的昵称、签名字段直接渲染,存储型XSS的高发区;三是Html.Raw被滥用,尤其是在渲染后台配置内容时想当然认为数据可信;四是前端使用innerHTML渲染接口返回的富文本,绕过了服务端的所有防护。

总结一下防护要点:默认信任Razor的自动编码,任何绕过编码的操作都要三思;根据输出上下文选择正确的编码器;富文本场景使用净化库做白名单过滤;配置CSP响应头作为兜底防线;关键Cookie设置HttpOnly和Secure属性;对所有用户输入做服务端校验。安全没有一劳永逸的方案,把这些手段组合起来形成纵深防御,才能真正抵御XSS攻击。

C# XSS防护ASP.NET Core跨站脚本攻击修改时间:2026-09-13 19:20:54

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260913/56195.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。