安全框架:会话管理Security Frame: Session Management

产品/服务Product/Service 文章Article
Azure ADAzure AD
IoT 设备IoT Device
Azure Document DBAzure Document DB
ADFSADFS
标识服务器Identity Server
Web 应用程序Web Application
Web APIWeb API

使用 Azure AD 时借助 ADAL 方法实现适当的注销Implement proper logout using ADAL methods when using Azure AD

标题Title 详细信息Details
组件Component Azure ADAzure AD
SDL 阶段SDL Phase 构建Build
适用的技术Applicable Technologies 泛型Generic
属性Attributes 空值N/A
参考References 空值N/A
步骤Steps 如果应用程序依赖于 Azure AD 颁发的访问令牌,注销事件处理程序应调用If the application relies on access token issued by Azure AD, the logout event handler should call

示例Example

HttpContext.GetOwinContext().Authentication.SignOut(OpenIdConnectAuthenticationDefaults.AuthenticationType, CookieAuthenticationDefaults.AuthenticationType)

示例Example

此外,应该通过调用 Session.Abandon() 方法来销毁用户的会话。It should also destroy user's session by calling Session.Abandon() method. 以下方法演示了用户注销的安全实现:Following method shows secure implementation of user logout:

    [HttpPost]
        [ValidateAntiForgeryToken]
        public void LogOff()
        {
            string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
            AuthenticationContext authContext = new AuthenticationContext(Authority + TenantId, new NaiveSessionCache(userObjectID));
            authContext.TokenCache.Clear();
            Session.Clear();
            Session.Abandon();
            Response.SetCookie(new HttpCookie("ASP.NET_SessionId", string.Empty));
            HttpContext.GetOwinContext().Authentication.SignOut(
                OpenIdConnectAuthenticationDefaults.AuthenticationType,
                CookieAuthenticationDefaults.AuthenticationType);
        } 

对生成的 SaS 令牌使用有限生存期Use finite lifetimes for generated SaS tokens

标题Title 详细信息Details
组件Component IoT 设备IoT Device
SDL 阶段SDL Phase 构建Build
适用的技术Applicable Technologies 泛型Generic
属性Attributes 空值N/A
参考References 空值N/A
步骤Steps 为了向 Azure IoT 中心进行身份验证而生成的 SaS 令牌应该附带有限的过期时间。SaS tokens generated for authenticating to Azure IoT Hub should have a finite expiry period. 请尽量缩短 SaS 令牌的生存期,以便在令牌泄露的情况下,限制这些令牌的可重放时间。Keep the SaS token lifetimes to a minimum to limit the amount of time they can be replayed in case the tokens are compromised.

对生成的资源令牌使用最短的令牌生存期Use minimum token lifetimes for generated Resource tokens

标题Title 详细信息Details
组件Component Azure Document DBAzure Document DB
SDL 阶段SDL Phase 构建Build
适用的技术Applicable Technologies 泛型Generic
属性Attributes 空值N/A
参考References 空值N/A
步骤Steps 将资源令牌的时间跨度减至所需的最小值。Reduce the timespan of resource token to a minimum value required. 资源令牌的有效时间跨度默认为 1 小时。Resource tokens have a default valid timespan of 1 hour.

使用 ADFS 时借助 WsFederation 方法实现适当的注销Implement proper logout using WsFederation methods when using ADFS

标题Title 详细信息Details
组件Component ADFSADFS
SDL 阶段SDL Phase 构建Build
适用的技术Applicable Technologies 泛型Generic
属性Attributes 空值N/A
参考References 空值N/A
步骤Steps 如果应用程序依赖于 ADFS 颁发的 STS 令牌,注销事件处理程序应调用 WSFederationAuthenticationModule.FederatedSignOut() 方法来注销用户。If the application relies on STS token issued by ADFS, the logout event handler should call WSFederationAuthenticationModule.FederatedSignOut() method to log out the user. 此外,应销毁当前会话,重置会话令牌值并将其设为 null。Also the current session should be destroyed, and the session token value should be reset and nullified.

示例Example

        [HttpPost, ValidateAntiForgeryToken]
        [Authorization]
        public ActionResult SignOut(string redirectUrl)
        {
            if (!this.User.Identity.IsAuthenticated)
            {
                return this.View("LogOff", null);
            }

            // Removes the user profile.
            this.Session.Clear();
            this.Session.Abandon();
            HttpContext.Current.Response.Cookies.Add(new System.Web.HttpCookie("ASP.NET_SessionId", string.Empty)
                {
                    Expires = DateTime.Now.AddDays(-1D),
                    Secure = true,
                    HttpOnly = true
                });

            // Signs out at the specified security token service (STS) by using the WS-Federation protocol.
            Uri signOutUrl = new Uri(FederatedAuthentication.WSFederationAuthenticationModule.Issuer);
            Uri replyUrl = new Uri(FederatedAuthentication.WSFederationAuthenticationModule.Realm);
            if (!string.IsNullOrEmpty(redirectUrl))
            {
                replyUrl = new Uri(FederatedAuthentication.WSFederationAuthenticationModule.Realm + redirectUrl);
            }
           //     Signs out of the current session and raises the appropriate events.
            var authModule = FederatedAuthentication.WSFederationAuthenticationModule;
            authModule.SignOut(false);
        //     Signs out at the specified security token service (STS) by using the WS-Federation
        //     protocol.            
            WSFederationAuthenticationModule.FederatedSignOut(signOutUrl, replyUrl);
            return new RedirectResult(redirectUrl);
        }

使用标识服务器时实现适当的注销Implement proper logout when using Identity Server

标题Title 详细信息Details
组件Component 标识服务器Identity Server
SDL 阶段SDL Phase 构建Build
适用的技术Applicable Technologies 泛型Generic
属性Attributes 空值N/A
参考References IdentityServer3 - 联合注销IdentityServer3-Federated sign out
步骤Steps IdentityServer 支持与外部标识提供者联合。IdentityServer supports the ability to federate with external identity providers. 如果用户从某个上游标识提供者注销,根据所用的协议,当该用户注销时,可能会出现通知。这样,IdentityServer 便可以通知其客户端,使这些客户端也将该用户注销。请参阅参考部分中的文档了解实施详细信息。When a user signs out of an upstream identity provider, depending upon the protocol used, it might be possible to receive a notification when the user signs out. It allows IdentityServer to notify its clients so they can also sign the user out. Check the documentation in the references section for the implementation details.

可通过 HTTPS 使用的应用程序必须使用安全 CookieApplications available over HTTPS must use secure cookies

标题Title 详细信息Details
组件Component Web 应用程序Web Application
SDL 阶段SDL Phase 构建Build
适用的技术Applicable Technologies 泛型Generic
属性Attributes EnvironmentType - OnPremEnvironmentType - OnPrem
参考References httpCookies 元素(ASP.NET 设置架构)HttpCookie.Secure 属性httpCookies Element (ASP.NET Settings Schema), HttpCookie.Secure Property
步骤Steps 通常只能从 Cookie 限定到的域访问这些 Cookie。Cookies are normally only accessible to the domain for which they were scoped. 遗憾的是,“域”的定义不包括协议,因此,通过 HTTPS 创建的 Cookie 可通过 HTTP 访问。Unfortunately, the definition of "domain" does not include the protocol so cookies that are created over HTTPS are accessible over HTTP. “secure”特性可向浏览器指明,只能通过 HTTPS 使用 Cookie。The "secure" attribute indicates to the browser that the cookie should only be made available over HTTPS. 请确保通过 HTTPS 设置的所有 Cookie 使用 secure 特性。Ensure that all cookies set over HTTPS use the secure attribute. 可在 web.config 文件通过将 requireSSL 属性设置为 true,来强制实施此要求。The requirement can be enforced in the web.config file by setting the requireSSL attribute to true. 这是一种首选方法,因为它会强制所有当前和未来的 Cookie 使用 secure 属性,而无需对代码进一步进行更改。It is the preferred approach because it will enforce the secure attribute for all current and future cookies without the need to make any additional code changes.

示例Example

<configuration>
  <system.web>
    <httpCookies requireSSL="true"/>
  </system.web>
</configuration>

即使使用 HTTP 访问应用程序,也会强制实施此设置。The setting is enforced even if HTTP is used to access the application. 如果使用 HTTP 访问应用程序,此设置会中断应用程序,因为 Cookie 设置为使用 secure 属性,而浏览器不会将这些 Cookie 发回到应用程序。If HTTP is used to access the application, the setting breaks the application because the cookies are set with the secure attribute and the browser will not send them back to the application.

标题Title 详细信息Details
组件Component Web 应用程序Web Application
SDL 阶段SDL Phase 构建Build
适用的技术Applicable Technologies Web 窗体、MVC5Web Forms, MVC5
属性Attributes EnvironmentType - OnPremEnvironmentType - OnPrem
参考References 空值N/A
步骤Steps 如果 Web 应用程序是信赖方,IdP 是 ADFS 服务器,则可以通过在 web.config 的 system.identityModel.services 节中将 requireSSL 设置为 True,来配置 FedAuth 令牌的 secure 特性:When the web application is the Relying Party, and the IdP is ADFS server, the FedAuth token's secure attribute can be configured by setting requireSSL to True in system.identityModel.services section of web.config:

示例Example

  <system.identityModel.services>
    <federationConfiguration>
      <!-- Set requireSsl=true; domain=application domain name used by FedAuth cookies (Ex: .gdinfra.com); -->
      <cookieHandler requireSsl="true" persistentSessionLifetime="0.0:20:0" />
    ....  
    </federationConfiguration>
  </system.identityModel.services>
标题Title 详细信息Details
组件Component Web 应用程序Web Application
SDL 阶段SDL Phase 构建Build
适用的技术Applicable Technologies 泛型Generic
属性Attributes 空值N/A
参考References 安全 Cookie 特性Secure Cookie Attribute
步骤Steps 为了缓解跨站点脚本 (XSS) 攻击造成的信息泄露风险,Cookie 中引入了新特性 httpOnly,所有主流浏览器都支持此特性。To mitigate the risk of information disclosure with a cross-site scripting (XSS) attack, a new attribute - httpOnly - was introduced to cookies and is supported by all major browsers. 此属性指定不能通过脚本访问 Cookie。The attribute specifies that a cookie is not accessible through script. Web 应用程序可以使用 HttpOnly Cookie 来减少通过脚本窃取 Cookie 中包含的敏感信息并将其发送到攻击者网站的可能性。By using HttpOnly cookies, a web application reduces the possibility that sensitive information contained in the cookie can be stolen via script and sent to an attacker's website.

示例Example

所有使用 Cookie 的基于 HTTP 的应用程序应该通过在 web.config 中实现以下配置,在 Cookie 定义中指定 HttpOnly:All HTTP-based applications that use cookies should specify HttpOnly in the cookie definition, by implementing following configuration in web.config:

<system.web>
.
.
   <httpCookies requireSSL="false" httpOnlyCookies="true"/>
.
.
</system.web>
标题Title 详细信息Details
组件Component Web 应用程序Web Application
SDL 阶段SDL Phase 构建Build
适用的技术Applicable Technologies Web 窗体Web Forms
属性Attributes 空值N/A
参考References FormsAuthentication.RequireSSL 属性FormsAuthentication.RequireSSL Property
步骤Steps 可以使用配置元素的 requireSSL 特性,在 ASP.NET 应用程序的配置文件中设置 RequireSSL 属性值。The RequireSSL property value is set in the configuration file for an ASP.NET application by using the requireSSL attribute of the configuration element. 可通过设置 requireSSL 特性,在 ASP.NET 应用程序的 Web.config 文件中指定是否需要使用传输层安全性 (TLS)(以前称为 SSL(安全套接字层))将窗体身份验证 Cookie 返回到服务器。You can specify in the Web.config file for your ASP.NET application whether Transport Layer Security (TLS), previously known as SSL (Secure Sockets Layer), is required to return the forms-authentication cookie to the server by setting the requireSSL attribute.

示例Example

以下代码示例在 Web.config 文件中设置 requireSSL 特性。The following code example sets the requireSSL attribute in the Web.config file.

<authentication mode="Forms">
  <forms loginUrl="member_login.aspx" cookieless="UseCookies" requireSSL="true"/>
</authentication>
标题Title 详细信息Details
组件Component Web 应用程序Web Application
SDL 阶段SDL Phase 构建Build
适用的技术Applicable Technologies MVC5MVC5
属性Attributes EnvironmentType - OnPremEnvironmentType - OnPrem
参考References Windows Identity Foundation (WIF) 配置 – 第 II 部分Windows Identity Foundation (WIF) Configuration – Part II
步骤Steps 要为 FedAuth Cookie 设置 httpOnly 特性,应将 hideFromCsript 特性值应设置为 True。To set httpOnly attribute for FedAuth cookies, hideFromCsript attribute value should be set to True.

示例Example

以下配置显示正确的配置:Following configuration shows the correct configuration:

<federatedAuthentication>
<cookieHandler mode="Custom"
                       hideFromScript="true"
                       name="FedAuth"
                       path="/"
                       requireSsl="true"
                       persistentSessionLifetime="25">
</cookieHandler>
</federatedAuthentication>

缓解针对 ASP.NET 网页的跨站点请求伪造 (CSRF) 攻击Mitigate against Cross-Site Request Forgery (CSRF) attacks on ASP.NET web pages

标题Title 详细信息Details
组件Component Web 应用程序Web Application
SDL 阶段SDL Phase 构建Build
适用的技术Applicable Technologies 泛型Generic
属性Attributes 空值N/A
参考References 空值N/A
步骤Steps 跨站点请求伪造(CSRF 或 XSRF)攻击是指在在不同用户与网站建立的会话的安全上下文中执行操作。Cross-site request forgery (CSRF or XSRF) is a type of attack in which an attacker can carry out actions in the security context of a different user's established session on a web site. 其企图是在目标网站专门依赖使用会话 Cookie 对收到的请求进行身份验证的情况下修改或删除内容。The goal is to modify or delete content, if the targeted web site relies exclusively on session cookies to authenticate received request. 攻击者可能会利用此漏洞,获取不同用户的浏览器并在用户已登录到的有漏洞站点中使用某个命令加载 URL。An attacker could exploit this vulnerability by getting a different user's browser to load a URL with a command from a vulnerable site on which the user is already logged in. 攻击者可以使用多种方式实现此目的,例如,托管一个不同的网站用于从有漏洞的服务器加载资源,或者诱骗用户点击某个链接。There are many ways for an attacker to do that, such as by hosting a different web site that loads a resource from the vulnerable server, or getting the user to click a link. 如果服务器向客户端发送一个附加令牌,要求客户端在将来的所有请求中包含该令牌,并验证将来的所有请求是否包含与当前会话相关的令牌(例如,使用 ASP.NET AntiForgeryToken 或 ViewState),则可以避免这种攻击。The attack can be prevented if the server sends an additional token to the client, requires the client to include that token in all future requests, and verifies that all future requests include a token that pertains to the current session, such as by using the ASP.NET AntiForgeryToken or ViewState.
标题Title 详细信息Details
组件Component Web 应用程序Web Application
SDL 阶段SDL Phase 构建Build
适用的技术Applicable Technologies MVC5、MVC6MVC5, MVC6
属性Attributes 空值N/A
参考References ASP.NET MVC 和网页中的 XSRF/CSRF 预防XSRF/CSRF Prevention in ASP.NET MVC and Web Pages
步骤Steps 反 CSRF 和 ASP.NET MVC 窗体 - 例如,在视图中使用 AntiForgeryToken 帮助器方法;将 Html.AntiForgeryToken() 放入窗体。Anti-CSRF and ASP.NET MVC forms - Use the AntiForgeryToken helper method on Views; put an Html.AntiForgeryToken() into the form, for example,

示例Example

@using (Html.BeginForm("UserProfile", "SubmitUpdate")) { 
    @Html.ValidationSummary(true) 
    @Html.AntiForgeryToken()
    <fieldset> 

示例Example

<form action="/UserProfile/SubmitUpdate" method="post">
    <input name="__RequestVerificationToken" type="hidden" value="saTFWpkKN0BYazFtN6c4YbZAmsEwG0srqlUqqloi/fVgeV2ciIFVmelvzwRZpArs" />
    <!-- rest of form goes here -->
</form>

示例Example

同时,Html.AntiForgeryToken() 将为访问者提供一个名为 __RequestVerificationToken 的 Cookie,其值与上面所示的随机隐藏值相同。At the same time, Html.AntiForgeryToken() gives the visitor a cookie called __RequestVerificationToken, with the same value as the random hidden value shown above. 接下来,要验证传入的窗体发布内容,请将 [ValidateAntiForgeryToken] 筛选器添加到目标操作方法。Next, to validate an incoming form post, add the [ValidateAntiForgeryToken] filter to the target action method. 例如:For example:

[ValidateAntiForgeryToken]
public ViewResult SubmitUpdate()
{
// ... etc.
}

可以检查以下各项的授权筛选器:Authorization filter that checks that:

  • 传入的请求是否包含名为 __RequestVerificationToken 的 CookieThe incoming request has a cookie called __RequestVerificationToken
  • 传入的请求是否包含名为 __RequestVerificationToken 的 Request.Form 条目The incoming request has a Request.Form entry called __RequestVerificationToken
  • 这些 Cookie 是否与 Request.Form 值匹配。假设一切正常,则请求可以顺利传输。These cookie and Request.Form values match Assuming all is well, the request goes through as normal. 否则,授权会失败并出现消息“未提供所需的防伪令牌或者该令牌无效”。But if not, then an authorization failure with message “A required anti-forgery token was not supplied or was invalid”.

示例Example

反 CSRF 和 AJAX:窗体令牌可能对 AJAX 请求造成问题,因为 AJAX 请求可以发送 JSON 数据,但不能发送 HTML 窗体数据。Anti-CSRF and AJAX: The form token can be a problem for AJAX requests, because an AJAX request might send JSON data, not HTML form data. 一种解决方法是在自定义 HTTP 标头中发送令牌。One solution is to send the tokens in a custom HTTP header. 以下代码使用 Razor 语法生成令牌,然后将令牌添加到 AJAX 请求。The following code uses Razor syntax to generate the tokens, and then adds the tokens to an AJAX request.

<script>
    @functions{
        public string TokenHeaderValue()
        {
            string cookieToken, formToken;
            AntiForgery.GetTokens(null, out cookieToken, out formToken);
            return cookieToken + ":" + formToken;                
        }
    }

    $.ajax("api/values", {
        type: "post",
        contentType: "application/json",
        data: {  }, // JSON data goes here
        dataType: "json",
        headers: {
            'RequestVerificationToken': '@TokenHeaderValue()'
        }
    });
</script>

示例Example

处理请求时,请从请求标头中提取令牌。When you process the request, extract the tokens from the request header. 然后调用 AntiForgery.Validate 方法来验证令牌。Then call the AntiForgery.Validate method to validate the tokens. 如果令牌无效,Validate 方法将引发异常。The Validate method throws an exception if the tokens are not valid.

void ValidateRequestHeader(HttpRequestMessage request)
{
    string cookieToken = "";
    string formToken = "";

    IEnumerable<string> tokenHeaders;
    if (request.Headers.TryGetValues("RequestVerificationToken", out tokenHeaders))
    {
        string[] tokens = tokenHeaders.First().Split(':');
        if (tokens.Length == 2)
        {
            cookieToken = tokens[0].Trim();
            formToken = tokens[1].Trim();
        }
    }
    AntiForgery.Validate(cookieToken, formToken);
}
标题Title 详细信息Details
组件Component Web 应用程序Web Application
SDL 阶段SDL Phase 构建Build
适用的技术Applicable Technologies Web 窗体Web Forms
属性Attributes 空值N/A
参考References 利用 ASP.NET 内置功能来防范 Web 攻击Take Advantage of ASP.NET Built-in Features to Fend Off Web Attacks
步骤Steps 可以通过将 ViewStateUserKey 设置为某个随机字符串(该字符串因用户而异,可根据用户 ID 设置,最好是根据会话 ID 设置),来缓解基于 Web 窗体的应用程序中的 CSRF 攻击。CSRF attacks in WebForm based applications can be mitigated by setting ViewStateUserKey to a random string that varies for each user - user ID or, better yet, session ID. 出于技术和社会方面的多种原因,根据会话 ID 设置此属性要好得多,因为会话 ID 不可预测、会超时,并且根据不同的用户而异。For a number of technical and social reasons, session ID is a much better fit because a session ID is unpredictable, times out, and varies on a per-user basis.

示例Example

需要在所有页面中添加以下代码:Here's the code you need to have in all of your pages:

void Page_Init (object sender, EventArgs e) {
   ViewStateUserKey = Session.SessionID;
   :
}

设置会话的非活动生存期Set up session for inactivity lifetime

标题Title 详细信息Details
组件Component Web 应用程序Web Application
SDL 阶段SDL Phase 构建Build
适用的技术Applicable Technologies 泛型Generic
属性Attributes 空值N/A
参考References HttpSessionState.Timeout 属性HttpSessionState.Timeout Property
步骤Steps 会话超时是指由于用户在某个间隔时间(由 Web 服务器定义)内未在网站上执行任何操作而发生的事件。Session timeout represents the event occurring when a user does not perform any action on a web site during an interval (defined by web server). 服务器端发生该事件时,会将用户会话的状态更改为“invalid”(即,“不再使用”),并指示 Web 服务器销毁该会话(删除其中包含的所有数据)。The event, on server side, change the status of the user session to 'invalid' (for example "not used anymore") and instruct the web server to destroy it (deleting all data contained into it). 以下代码示例在 Web.config 文件中将超时会话特性设置为 15 分钟。The following code example sets the timeout session attribute to 15 minutes in the Web.config file.

示例Example

<configuration>
  <system.web>
    <sessionState mode="InProc" cookieless="true" timeout="15" />
  </system.web>
</configuration>

通过应用程序实现适当的注销Implement proper logout from the application

标题Title 详细信息Details
组件Component Web 应用程序Web Application
SDL 阶段SDL Phase 构建Build
适用的技术Applicable Technologies 泛型Generic
属性Attributes 空值N/A
参考References 空值N/A
步骤Steps 当用户按下注销按钮时,从应用程序执行适当的注销。Perform proper Sign Out from the application, when user presses log out button. 注销后,应用程序应销毁用户的会话,重置会话 Cookie 值并将其设置为 null,同时重置身份验证 Cookie 值并将其设置为 null。Upon logout, application should destroy user's session, and also reset and nullify session cookie value, along with resetting and nullifying authentication cookie value. 此外,如果多个会话绑定到单个用户标识,在超时或注销时,必须在服务器端统一终止这些会话。Also, when multiple sessions are tied to a single user identity, they must be collectively terminated on the server side at timeout or logout. 最后,确保可在每个页面上使用注销功能。Lastly, ensure that Logout functionality is available on every page.

缓解针对 ASP.NET Web API 的跨站点请求伪造 (CSRF) 攻击Mitigate against Cross-Site Request Forgery (CSRF) attacks on ASP.NET Web APIs

标题Title 详细信息Details
组件Component Web APIWeb API
SDL 阶段SDL Phase 构建Build
适用的技术Applicable Technologies 泛型Generic
属性Attributes 空值N/A
参考References 空值N/A
步骤Steps 跨站点请求伪造(CSRF 或 XSRF)攻击是指在在不同用户与网站建立的会话的安全上下文中执行操作。Cross-site request forgery (CSRF or XSRF) is a type of attack in which an attacker can carry out actions in the security context of a different user's established session on a web site. 其企图是在目标网站专门依赖使用会话 Cookie 对收到的请求进行身份验证的情况下修改或删除内容。The goal is to modify or delete content, if the targeted web site relies exclusively on session cookies to authenticate received request. 攻击者可能会利用此漏洞,获取不同用户的浏览器并在用户已登录到的有漏洞站点中使用某个命令加载 URL。An attacker could exploit this vulnerability by getting a different user's browser to load a URL with a command from a vulnerable site on which the user is already logged in. 攻击者可以使用多种方式实现此目的,例如,托管一个不同的网站用于从有漏洞的服务器加载资源,或者诱骗用户点击某个链接。There are many ways for an attacker to do that, such as by hosting a different web site that loads a resource from the vulnerable server, or getting the user to click a link. 如果服务器向客户端发送一个附加令牌,要求客户端在将来的所有请求中包含该令牌,并验证将来的所有请求是否包含与当前会话相关的令牌(例如,使用 ASP.NET AntiForgeryToken 或 ViewState),则可以避免这种攻击。The attack can be prevented if the server sends an additional token to the client, requires the client to include that token in all future requests, and verifies that all future requests include a token that pertains to the current session, such as by using the ASP.NET AntiForgeryToken or ViewState.
标题Title 详细信息Details
组件Component Web APIWeb API
SDL 阶段SDL Phase 构建Build
适用的技术Applicable Technologies MVC5、MVC6MVC5, MVC6
属性Attributes 空值N/A
参考References 防止 ASP.NET Web API 中的跨站点请求伪造 (CSRF) 攻击Preventing Cross-Site Request Forgery (CSRF) Attacks in ASP.NET Web API
步骤Steps 反 CSRF 和 AJAX:窗体令牌可能对 AJAX 请求造成问题,因为 AJAX 请求可以发送 JSON 数据,但不能发送 HTML 窗体数据。Anti-CSRF and AJAX: The form token can be a problem for AJAX requests, because an AJAX request might send JSON data, not HTML form data. 一种解决方法是在自定义 HTTP 标头中发送令牌。One solution is to send the tokens in a custom HTTP header. 以下代码使用 Razor 语法生成令牌,然后将令牌添加到 AJAX 请求。The following code uses Razor syntax to generate the tokens, and then adds the tokens to an AJAX request.

示例Example

<script>
    @functions{
        public string TokenHeaderValue()
        {
            string cookieToken, formToken;
            AntiForgery.GetTokens(null, out cookieToken, out formToken);
            return cookieToken + ":" + formToken;                
        }
    }
    $.ajax("api/values", {
        type: "post",
        contentType: "application/json",
        data: {  }, // JSON data goes here
        dataType: "json",
        headers: {
            'RequestVerificationToken': '@TokenHeaderValue()'
        }
    });
</script>

示例Example

处理请求时,请从请求标头中提取令牌。When you process the request, extract the tokens from the request header. 然后调用 AntiForgery.Validate 方法来验证令牌。Then call the AntiForgery.Validate method to validate the tokens. 如果令牌无效,Validate 方法将引发异常。The Validate method throws an exception if the tokens are not valid.

void ValidateRequestHeader(HttpRequestMessage request)
{
    string cookieToken = "";
    string formToken = "";

    IEnumerable<string> tokenHeaders;
    if (request.Headers.TryGetValues("RequestVerificationToken", out tokenHeaders))
    {
        string[] tokens = tokenHeaders.First().Split(':');
        if (tokens.Length == 2)
        {
            cookieToken = tokens[0].Trim();
            formToken = tokens[1].Trim();
        }
    }
    AntiForgery.Validate(cookieToken, formToken);
}

示例Example

反 CSRF 和 ASP.NET MVC 窗体 - 例如,在视图中使用 AntiForgeryToken 帮助器方法;将 Html.AntiForgeryToken() 放入窗体。Anti-CSRF and ASP.NET MVC forms - Use the AntiForgeryToken helper method on Views; put an Html.AntiForgeryToken() into the form, for example,

@using (Html.BeginForm("UserProfile", "SubmitUpdate")) { 
    @Html.ValidationSummary(true) 
    @Html.AntiForgeryToken()
    <fieldset> 
}

示例Example

上述示例输出如下所示的信息:The example above will output something like the following:

<form action="/UserProfile/SubmitUpdate" method="post">
    <input name="__RequestVerificationToken" type="hidden" value="saTFWpkKN0BYazFtN6c4YbZAmsEwG0srqlUqqloi/fVgeV2ciIFVmelvzwRZpArs" />
    <!-- rest of form goes here -->
</form>

示例Example

同时,Html.AntiForgeryToken() 将为访问者提供一个名为 __RequestVerificationToken 的 Cookie,其值与上面所示的随机隐藏值相同。At the same time, Html.AntiForgeryToken() gives the visitor a cookie called __RequestVerificationToken, with the same value as the random hidden value shown above. 接下来,要验证传入的窗体发布内容,请将 [ValidateAntiForgeryToken] 筛选器添加到目标操作方法。Next, to validate an incoming form post, add the [ValidateAntiForgeryToken] filter to the target action method. 例如:For example:

[ValidateAntiForgeryToken]
public ViewResult SubmitUpdate()
{
// ... etc.
}

可以检查以下各项的授权筛选器:Authorization filter that checks that:

  • 传入的请求是否包含名为 __RequestVerificationToken 的 CookieThe incoming request has a cookie called __RequestVerificationToken
  • 传入的请求是否包含名为 __RequestVerificationToken 的 Request.Form 条目The incoming request has a Request.Form entry called __RequestVerificationToken
  • 这些 Cookie 是否与 Request.Form 值匹配。假设一切正常,则请求可以顺利传输。These cookie and Request.Form values match Assuming all is well, the request goes through as normal. 否则,授权会失败并出现消息“未提供所需的防伪令牌或者该令牌无效”。But if not, then an authorization failure with message “A required anti-forgery token was not supplied or was invalid”.
标题Title 详细信息Details
组件Component Web APIWeb API
SDL 阶段SDL Phase 构建Build
适用的技术Applicable Technologies MVC5、MVC6MVC5, MVC6
属性Attributes 标识提供者 - ADFS,标识提供者 - Azure ADIdentity Provider - ADFS, Identity Provider - Azure AD
参考References 在 ASP.NET Web API 2.2 中使用单个帐户和本地登录名保护 Web APISecure a Web API with Individual Accounts and Local Login in ASP.NET Web API 2.2
步骤Steps 如果 Web API 是使用 OAuth 2.0 保护的,则它需要在授权请求标头中包含一个持有者令牌,仅当该令牌有效时,才向请求授予访问权限。If the Web API is secured using OAuth 2.0, then it expects a bearer token in Authorization request header and grants access to the request only if the token is valid. 与基于 Cookie 的身份验证不同,浏览器不会将持有者令牌附加到请求。Unlike cookie based authentication, browsers do not attach the bearer tokens to requests. 请求方客户端需要在请求标头中显式附加持有者令牌。The requesting client needs to explicitly attach the bearer token in the request header. 因此,对于使用 OAuth 2.0 保护的 ASP.NET Web API,持有者令牌被视为一种防范 CSRF 攻击的措施。Therefore, for ASP.NET Web APIs protected using OAuth 2.0, bearer tokens are considered as a defense against CSRF attacks. 请注意,如果应用程序的 MVC 部分使用窗体身份验证(即,使用 Cookie),则 MVC Web 应用必须使用防伪令牌。Please note that if the MVC portion of the application uses forms authentication (i.e., uses cookies), anti-forgery tokens have to be used by the MVC web app.

示例Example

必须告知 Web API 只能依赖于持有者令牌,而不能依赖于 Cookie。The Web API has to be informed to rely ONLY on bearer tokens and not on cookies. 此操作可通过 WebApiConfig.Register 方法中的以下配置完成:It can be done by the following configuration in WebApiConfig.Register method:

config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

SuppressDefaultHostAuthentication 方法通过 IIS 或 OWIN 中间件告知 Web API 忽略在请求到达 Web API 管道前发生的任何身份验证。The SuppressDefaultHostAuthentication method tells Web API to ignore any authentication that happens before the request reaches the Web API pipeline, either by IIS or by OWIN middleware. 如此,便可以限制 Web API 仅使用持有者令牌进行身份验证。That way, we can restrict Web API to authenticate only using bearer tokens.