【ASP.NET Web API教程】5.5 ASP.NET Web API中的HTTP Cookie

原文:【ASP.NET Web API教程】5.5 ASP.NET Web API中的HTTP Cookie

5.5 HTTP Cookies in ASP.NET Web API
5.5 ASP.NET Web API中的HTTP Cookie

本文引自:http://www.asp.net/web-api/overview/working-with-http/http-cookies

By Mike Wasson|September 17, 2012
作者:Mike Wasson | 日期:2012-9-17

This topic describes how to send and receive HTTP cookies in Web API.
本主题描述如何在Web API中发送和接收HTTP Cookie。

Background on HTTP Cookies
HTTP Cookie的背景知识

This section gives a brief overview of how cookies are implemented at the HTTP level. For details, consult RFC 6265.
本小节给出在HTTP层面上如何实现Cookies,详细参考RFC 6265

A cookie is a piece of data that a server sends in the HTTP response. The client (optionally) stores the cookie and returns it on subsequet requests. This allows the client and server to share state. To set a cookie, the server includes a Set-Cookie header in the response. The format of a cookie is a name-value pair, with optional attributes. For example:
Cookie是服务器在HTTP响应中发送的一个数据片段。客户端存储此Cookie(可选),并在后继的请求中返回它。这让客户端和服务器端可以共享状态。为了设置一个Cookie,服务器需要在响应中包含一个Set-Cookie报头。Cookie的格式是一个“名字-值”对,并带有一些可选属性。例如:

Set-Cookie: session-id=1234567

Here is an example with attributes:
以下是一个带有属性的示例:

Set-Cookie: session-id=1234567; max-age=86400; domain=example.com; path=/;

To return a cookie to the server, the client includes a Cookie header in later requests.
为了将一个Cookie返回给服务器,客户端在后继的请求中要包含一个Cookie报头。

Cookie: session-id=1234567

An HTTP response can include multiple Set-Cookie headers.
一个HTTP响应可以包含多个Set-Cookie报头。

Set-Cookie: session-token=abcdef;
Set-Cookie: session-id=1234567; 

The client returns multiple cookies using a single Cookie header.
客户端用一个单一的Cookie报头返回多个Cookie。

Cookie: session-id=1234567; session-token=abcdef;

The scope and duration of a cookie are controlled by following attributes in the Set-Cookie header:
Cookie的范围和期限是受Set-Cookie报头的以下属性控制的:

  • Domain: Tells the client which domain should receive the cookie. For example, if the domain is “example.com”, the client returns the cookie to every subdomain of example.com. If not specified, the domain is the origin server.
    Domain(主域,或简称为):告诉客户端哪一个域应当接收此Cookie。例如,如果Domain是“example.com”,那么客户端要把Cookie返回给example.com的每个子域。如果未指定,这个域便是原服务器。
  • Path: Restricts the cookie to the specified path within the domain. If not specified, the path of the request URI is used.
    Path(路径):将Cookie限制到主域的特定路径。如果未指定,则使用请求URI的路径。
  • Expires: Sets an expiration date for the cookie. The client deletes the cookie when it expires.
    Expires(过期):设置Cookie的过期日期。当Cookie过期时,客户端删除此Cookie。
  • Max-Age: Sets the maximum age for the cookie. The client deletes the cookie when it reaches the maximum age.
    Max-Age(最大年龄):设置Cookie的最大年龄。当Cookie达到最大年龄时,客户端删除此Cookie。

If both Expires and Max-Age are set, Max-Age takes precedence. If neither is set, the client deletes the cookie when the current session ends. (The exact meaning of “session” is determined by the user-agent.)
如果Expires和Max-Age都设置,则Max-Age优先。如果都未设置,在当前会话结束时,客户端删除Cookie。(“会话”的确切含意是由用户代理确定的。)

However, be aware that clients may ignore cookies. For example, a user might disable cookies for privacy reasons. Clients may delete cookies before they expire, or limit the number of cookies stored. For privacy reasons, clients often reject “third party” cookies, where the domain does not match the origin server. In short, the server should not rely on getting back the cookies that it sets.
然而,要意识到客户端可能会忽略Cookie。例如,一个用户可能由于私人原因禁用了Cookies。客户端可能会在过期之前删除Cookies,或限制保存Cookies的数目。出于私有原因,客户端通常会拒绝与源服务器域不匹配的“第三方”Cookie。简言之,服务器不应该对取回它所设置的Cookie有依赖性。

Cookies in Web API
Web API中的Cookies

To add a cookie to an HTTP response, create a CookieHeaderValue instance that represents the cookie. Then call the AddCookies extension method, which is defined in the System.Net.Http. HttpResponseHeadersExtensions class, to add the cookie.
为了对一个HTTP响应添加Cookie,需要创建一个表示Cookie的CookieHeaderValue实例。然后调用AddCookies扩展方法(这是在System.Net.Http.HttpResponseHeadersExtensions类中定义的),以添加一个Cookie。

For example, the following code adds a cookie within a controller action:
例如,以下代码在一个控制器动作中添加了一个Cookie:

public HttpResponseMessage Get()
{
    var resp = new HttpResponseMessage(); 
    var cookie = new CookieHeaderValue("session-id", "12345");
    cookie.Expires = DateTimeOffset.Now.AddDays(1);
    cookie.Domain = Request.RequestUri.Host;
    cookie.Path = "/"; 
    resp.Headers.AddCookies(new CookieHeaderValue[] { cookie });
    return resp;
}

Notice that AddCookies takes an array of CookieHeaderValue instances.
注意,AddCookies采用的是一个CookieHeaderValue实例数组。

To extract the cookies from a client request, call the GetCookies method:
为了提取客户端请求的Cookie,需要调用GetCookies方法:

string sessionId = ""; 
CookieHeaderValue cookie = Request.Headers.GetCookies("session-id").FirstOrDefault();
if (cookie != null)
{
    sessionId = cookie["session-id"].Value;
}

A CookieHeaderValue contains a collection of CookieState instances. Each CookieState represents one cookie. Use the indexer method to get a CookieState by name, as shown.
CookieHeaderValue含有CookieState实例的集合。每个CookieState表示一个Cookie。使用索引器方法(指上述代码最后一行的cookie["session-id"] — 译者注)可以得到由名称表示的CookieState,如上所示。

Structured Cookie Data
结构化的Cookie数据

Many browsers limit how many cookies they will store—both the total number, and the number per domain. Therefore, it can be useful to put structured data into a single cookie, instead of setting multiple cookies.
许多浏览器会限制其存储的Cookie数 — Cookie总数和每个域的Cookie数。因此,把结构化的数据放入一个Cookie而不是设置多个Cookie可能是有用的。

RFC 6265 does not define the structure of cookie data.
RFC 6265并未定义Cookie数据的结构。

Using the CookieHeaderValue class, you can pass a list of name-value pairs for the cookie data. These name-value pairs are encoded as URL-encoded form data in the Set-Cookie header:
使用CookieHeaderValue类,你可以为Cookie数据传递一组“名字-值”对。这些“名字-值”对是在Set-Cookie报头中作为URL编码的表单数据进行编码的:

var resp = new HttpResponseMessage();
var nv = new NameValueCollection();
nv["sid"] = "12345";
nv["token"] = "abcdef";
nv["theme"] = "dark blue";
var cookie = new CookieHeaderValue("session", nv);  
resp.Headers.AddCookies(new CookieHeaderValue[] { cookie });

The previous code produces the following Set-Cookie header:
上述代码产生以下Set-Cookie报头:

Set-Cookie: session=sid=12345&token=abcdef&theme=dark+blue;

The CookieState class provides an indexer method to read the sub-values from a cookie in the request message:
CookieState类提供了一个索引器方法,以读取请求消息中Cookie的子值(Sub-values):

string sessionId = "";
string sessionToken = "";
string theme = ""; 
CookieHeaderValue cookie = Request.Headers.GetCookies("session").FirstOrDefault();
if (cookie != null)
{
    CookieState cookieState = cookie["session"]; 
    sessionId = cookieState["sid"];
    sessionToken = cookieState["token"];
    theme = cookieState["theme"];
}

Example: Set and Retrieve Cookies in a Message Handler
示例:在消息处理器中设置和接收Cookie

The previous examples showed how to use cookies from within a Web API controller. Another option is to use message handlers. Message handlers are invoked earlier in the pipeline than controllers. A message handler can read cookies from the request before the request reaches the controller, or add cookies to the response after the controller generates the response.
前述示例演示了如何使用来自Web API控制器的Cookie。另一种选择是使用“消息处理器(Message Handler,也可以称为消息处理程序 — 译者注)”。消息处理器的调用在请求管线中要早于控制器。消息处理器可以在请求到达控制器之前读取请求的Cookie,或者,在控制器生成响应之后将Cookie添加到响应(如下图所示)。

The following code shows a message handler for creating session IDs. The session ID is stored in a cookie. The handler checks the request for the session cookie. If the request does not include the cookie, the handler generates a new session ID. In either case, the handler stores the session ID in the HttpRequestMessage.Properties property bag. It also adds the session cookie to the HTTP response.
以下代码演示了一个创建会话ID的消息处理器。会话ID是存储在一个Cookie中的。该处理器检查请求的会话Cookie。如果请求不包含Cookie,处理器便生成一个新会话的ID。在任一情况下,处理器都会将这个会话ID存储在HttpRequestMessage.Properties属性包中。它也将这个会话Cookie添加到HTTP响应。

This implementation does not validate that the session ID from the client was actually issued by the server. Don't use it as a form of authentication! The point of the example is to show HTTP cookie management.
如果客户端的会话ID实际是由服务器发布的,该实现不会验证它。不要把它用于认证场合!本例的关键是演示HTTP Cookie的管理。

using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http; 
public class SessionIdHandler : DelegatingHandler
{
    static public string SessionIdToken = "session-id"; 
    async protected override Task SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        string sessionId; 
        // Try to get the session ID from the request; otherwise create a new ID.
        // 尝试获取请求的会话ID,否则创建一个新的ID
        var cookie = request.Headers.GetCookies(SessionIdToken).FirstOrDefault();
        if (cookie == null)
        {
            sessionId = Guid.NewGuid().ToString();
        }
        else
        {
            sessionId = cookie[SessionIdToken].Value;
            try
            {
                Guid guid = Guid.Parse(sessionId);
            }
            catch (FormatException)
            {
                // Bad session ID. Create a new one.
                // 劣质会话ID,创建一个新的
                sessionId = Guid.NewGuid().ToString();
            }
        } 
        // Store the session ID in the request property bag.
        // 在请求的属性包中存储会话ID
        request.Properties[SessionIdToken] = sessionId; 
        // Continue processing the HTTP request.
        // 继续处理HTTP请求
        HttpResponseMessage response = await base.SendAsync(request, cancellationToken); 
        // Set the session ID as a cookie in the response message.
        // 将会话ID设置为响应消息中的一个Cookie
        response.Headers.AddCookies(new CookieHeaderValue[] {
            new CookieHeaderValue(SessionIdToken, sessionId)
        }); 
        return response;
    }
}

A controller can get the session ID from the HttpRequestMessage.Properties property bag.
控制器可以通过HttpRequestMessage.Properties属性包来获取会话ID。

public HttpResponseMessage Get()
{
    string sessionId = Request.Properties[SessionIdHandler.SessionIdToken] as string; 
    return new HttpResponseMessage()
    {
        Content = new StringContent("Your session ID = " + sessionId)
    };
}

看完此文如果觉得有所收获,请给个推荐

时间: 2024-10-11 19:19:18

【ASP.NET Web API教程】5.5 ASP.NET Web API中的HTTP Cookie的相关文章

【ASP.NET Web API教程】1 ASP.NET Web API入门

原文 [ASP.NET Web API教程]1 ASP.NET Web API入门 Getting Started with ASP.NET Web API第1章 ASP.NET Web API入门 摘自:http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api In this chapter, you'll learn: The basics of building an HTTP service using

【ASP.NET Web API教程】2 创建各种Web API

原文 [ASP.NET Web API教程]2 创建各种Web API Chapter 2: Creating Web APIs第2章 创建各种Web API 本文引自:http://www.asp.net/web-api/overview/creating-web-apis In this chapter, you'll learn:本章你将学习: End-to-end tutorials and samples for ASP.NET Web APIASP.NET Web API的端对端教程

【ASP.NET Web API教程】2.4 创建Web API的帮助页面

原文:[ASP.NET Web API教程]2.4 创建Web API的帮助页面 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. 2.4 Creating a Help Page for a Web API 2.4 创建Web API帮助页面 本文引自:http://www.asp.net/web-api/overview/creating-web-apis/creating-a-help-page-for-a-web-api By

ASP.NET MVC案例教程(基于ASP.NET MVC beta)—第七篇:闲话ASP.NET MVC

摘要 本文作为<ASP.NET MVC案例教程>的完结篇,仅从个人角度,发表一些对ASP.NET MVC框架的看法.并且在最后会附上本系列文章的Demo下 载. 前言 写这篇文章的目的,是想总结一些东西,以帮助朋友们更好的使用这个框架.但是,我又不像把官方列举的哪些优势.功能翻译过来列举在 这里.所以,我想干脆我就纯从个人观点上对这个框架评论一下吧.说的不好的,不对的还请批评指正.^_^ ASP.NET MVC--螺旋进步的产物 对于微软为什么要推出ASP.NET MVC,我们是无从得知的,也

ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第一篇:准备工作

前言 ASP.NET MVC作为微软官方的MVC解决方案,推出有一段时间了.可以说自动推出以来,一直广受关注.在经历了漫长的Preview 之后,前几天终于推出了其beta版.并且在官方文档中,微软声明最终的正式版与beta版相比不会有大的变化.所以,对于.NET平台的开发人 员来说,是时候学习ASP.NET MVC了. 本系列文章作为一个ASP.NET MVC的入门教程,将不会长篇大论介绍其中的概念及理论.而是通过 案例实践来学习ASP.NET MVC.在这系列文章中我将逐步完成一个"公告发布

ASP.NET 5系列教程 (五):在Visual Studio 2015中使用Grunt、Bower开发Web程序

基于Visual Studio 2015,你可以: 方便的管理前端包,如jQuery, Bootstrap, 或Angular. 自动运行任务,如LESS.JavaScript压缩.JSLint.JavaScript单元测试等. 方便的获得Web开发者生态圈的工具包. 为了实现这些场景,Visual Studio 2015已经内置了一些流行的第三方工具包: Bower:Web包管理器,Bower可以帮你安装前端包,包括JavaScript.CSS类库.对于服务器端包,请通过NuGet包管理. G

ASP.NET MVC案例教程(基于ASP.NET MVC beta)—第四篇:传递表单数据

前言 通过前几篇文章,我们已经能比较自如的使用ASP.NET MVC来呈现页面和数据了.但是,有一个大问题没有解决:如何处理表单 数据.例如,我们将要实现的公告发布功能,用户肯定是在某个表单页面输入标题.正文等内容,而后提交,然后表单数据要被传递到相应的 地方交由业务逻辑组件处理. 在传统的ASP.NET下,使用的是Model1模式,每个aspx页面有一个同名的aspx.cs文件,当提交表单时,默 认数据被提交到这个同名aspx.cs文件中某个方法下处理.但是,在ASP.NET MVC中,这种方

ASP.NET MVC案例教程(基于ASP.NET MVC beta)—第三篇:ASP.NET MVC全局观

前言 在上一篇文章中,我们实现了第一个ASP.NET MVC页面.对于没有接触过这个框架的朋友来说,可能对有些地方会迷惑,所以这 篇文章我将通过图示配合文字的方法,站在全局的角度介绍一些ASP.NET MVC的运行机制,这样可以帮助朋友们更好的理解后续文章. ^_^ 全局 首先我们来看一副图片,由于这幅图是我自己画的,不是摘自微软官方,所以如果有什么不到位的地方还望海涵! 首先,用户通过Web浏览器向服务器发送一条 url请求,这里请求的url不再是xxx.aspx格式,而是http://Hos

ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第六篇:拦截器

摘要 本文将对"MVC公告发布系统"的发布公告功能添加日志功能和异常处理功能,借此来讨论ASP.NET MVC中拦截器的使用方法. 一个小难题 我们继续完善"MVC公告发布系统",这次,我们的需求是对公告发布功能添加日志记录能力,即在发布公告前,记录一次,在 公告发布成功后,再记录一次.然后还要使得其具备异常处理,即当业务组件出现问题时,跳转到相应的错误页面并显示相应提示. 有 人可能笑了,这有什么难的,在DoRelease这个Action的开始和结束处各加入相应日

ASP.NET MVC案例教程(基于ASP.NET MVC beta)—第五篇:MVC整合Ajax

摘要 本文将从完成"输入数据验证"这个功能出发,逐渐展开ASP.NET MVC与Ajax结合的方法.首先,本文将使用ASP.NET MVC提供的同步方式完 成数据验证.而后,将分别结合ASP.NET AJAX和JQuery将这个功能重构成异步形式. 数据验证 在上一篇文章中,我们完成了发布公告的功能.但是从健壮性角度看,这个功能并不完善,因为一般情况下,我们输入的数据要符合一定的 约束条件,例如,在我们的例子中,我们至少不能将空字符串作为标题或内容吧.下面,我们来为程序加入数据验证功能