2015-03-31 25 views
3

我需要在WebAPI管道的身份验证步骤中读取/写入cookie。我为此创建了一个自定义过滤器。在HttpAuthenticationContext中为IAuthenticationFilter设置Cookie值

为了遵守自托管概念,将访问和写入客户端的安全方法是什么? Rick Strahl评论说,如果我们使用HttpContext.Current.Response.Cookies.Add(),并且我的应用程序是自托管的,则上下文可能不会存在。

那么如何使用HttpAuthenticationContext将客户端cookie写入客户端,并且仍然是自主主机安全的?

回答

1
HttpAuthenticationContext authContext; 
authContext.ActionContext.Response.Headers.AddCookies(/*cookies */); 

EDIT2

HttpAuthenticationContext authContext; 
var myCookie = new CookieHeaderValue("key", "value") 
authContext.ActionContext.Response.Headers.Add("Set-Cookie", myCookie.ToString()); 

编辑

的addCookie是位于System.Net.Http.Formatting.dll扩展方法(如版本v5.2.2.0的) ,并且扩展方法由位于命名空间System.Net.Http中的静态类HttpResponseHeadersExtensions声明。

  • 如果找不到扩展方法,请尝试找到HttpResponseHeadersExtensions类。

  • 如果找不到HttpResponseHeadersExtensions类,请尝试升级Web Api 2库。升级所有项目的WebApi2的Nuget软件包(对于那些讨厌像我这样的升级Nuget软件包的人),最有效的方法是在术语'version =“xxx”targetFramework =“net45的.config文件上进行全局搜索/替换如果你的老板或你的妈妈不会让你升级nuget软件包,在最坏的情况下,如果你的老板或你的妈妈不会让你升级nuget软件包,你总是可以采取反叛的态度和反编译包含的addCookie的代码,它看起来是这样的:

    using System; 
        using System.Collections.Generic; 
        using System.ComponentModel; 
        using System.Net.Http.Headers; 
        using System.Net.Http.Properties; 
        using System.Web.Http; 
        namespace System.Net.Http 
        { 
         /// <summary> Provides extension methods for the <see cref="T:System.Net.Http.Headers.HttpResponseHeaders" /> class. </summary> 
         [EditorBrowsable(EditorBrowsableState.Never)] 
         public static class HttpResponseHeadersExtensions 
         { 
          private const string SetCookie = "Set-Cookie"; 
          /// <summary> Adds cookies to a response. Each Set-Cookie header is represented as one <see cref="T:System.Net.Http.Headers.CookieHeaderValue" /> instance. A <see cref="T:System.Net.Http.Headers.CookieHeaderValue" /> contains information about the domain, path, and other cookie information as well as one or more <see cref="T:System.Net.Http.Headers.CookieState" /> instances. Each <see cref="T:System.Net.Http.Headers.CookieState" /> instance contains a cookie name and whatever cookie state is associate with that name. The state is in the form of a <see cref="T:System.Collections.Specialized.NameValueCollection" /> which on the wire is encoded as HTML Form URL-encoded data. This representation allows for multiple related "cookies" to be carried within the same Cookie header while still providing separation between each cookie state. A sample Cookie header is shown below. In this example, there are two <see cref="T:System.Net.Http.Headers.CookieState" /> with names state1 and state2 respectively. Further, each cookie state contains two name/value pairs (name1/value1 and name2/value2) and (name3/value3 and name4/value4). &lt;code&gt; Set-Cookie: state1:name1=value1&amp;amp;name2=value2; state2:name3=value3&amp;amp;name4=value4; domain=domain1; path=path1; &lt;/code&gt;</summary> 
          /// <param name="headers">The response headers</param> 
          /// <param name="cookies">The cookie values to add to the response.</param> 
          public static void AddCookies(this HttpResponseHeaders headers, IEnumerable<CookieHeaderValue> cookies) 
          { 
           if (headers == null) 
           { 
            throw Error.ArgumentNull("headers"); 
           } 
           if (cookies == null) 
           { 
            throw Error.ArgumentNull("cookies"); 
           } 
           foreach (CookieHeaderValue current in cookies) 
           { 
            if (current == null) 
            { 
             throw Error.Argument("cookies", Resources.CookieNull, new object[0]); 
            } 
            headers.TryAddWithoutValidation("Set-Cookie", current.ToString()); 
           } 
          } 
         } 
        } 
    
    • 你到底觉得有点愚蠢的开支SO 3 M UCH时间寻找一个扩展方法,当你意识到,在加入webapi2一个cookie在一行代码做简单:

headers.TryAddWithoutValidation(“设置Cookie”,新CookieHeaderValue( “核心价值”)); //标头为HttpResponseHeaders

+0

嗨@uzul,我做我的'Headers'对象没有'AddCookies'。有不同的命名空间吗?我的'HttpAuthenticationContext'是'System.Web.Http.Filters'命名空间的一部分。 – FrankO 2015-04-07 14:48:51

+0

Hi @FrankO的确,AddCookies是一个扩展方法:)你只需要添加组件System.Net.Http.Formatting.dll – uzul 2015-04-08 02:34:42

+0

嗨@uzul,我无法添加它,因为程序集已经是项目的一部分。 :)我尝试添加命名空间,但仍然无法使其工作。我正在使用Web API2和.Net 4.5。任何其他想法? – FrankO 2015-04-08 20:32:17

1

您不能从IAuthenticationFilter.AuthenticateAsync()内访问authContext.ActionContext.Response。那么,其实你可以,但只能设置一个新的响应,并快速完成其余的管道。

我有同样的问题(在验证成功后设置cookie的需要),并通过除实施IActionFilterIAuthenticationFilter解决了这个问题:

async Task<HttpResponseMessage> IActionFilter.ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation) 
{ 
    // Process the request pipeline and get the response (this causes the action to be executed) 
    HttpResponseMessage response = await continuation(); 

    // Here you get access to: 
    // - The request (actionContext.Request) 
    // - The response (response) and its cookies (response.Headers.AddCookies()) 
    // - The principal (actionContext.ControllerContext.RequestContext.Principal) 

    return response; 
} 

参见:Set cookie from Web Api 2 IAuthenticationFilter AuthenticateAsync method