Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Re-factor SecureOnly Cookie
  • Loading branch information
mythz committed Feb 14, 2013
1 parent 5d7a836 commit 09a5793
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 106 deletions.
15 changes: 7 additions & 8 deletions src/ServiceStack.Interfaces/ServiceHost/ICookies.cs
Expand Up @@ -3,12 +3,11 @@

namespace ServiceStack.ServiceHost
{
public interface ICookies
{
void DeleteCookie(string cookieName);
void AddCookie(Cookie cookie);
void AddPermanentCookie(string cookieName, string cookieValue);
void AddSessionCookie(string cookieName, string cookieValue);
void AddSessionCookie(string cookieName, string cookieValue, bool secureCookieAsRequest);
}
public interface ICookies
{
void DeleteCookie(string cookieName);
void AddCookie(Cookie cookie);
void AddPermanentCookie(string cookieName, string cookieValue, bool? secureOnly = null);
void AddSessionCookie(string cookieName, string cookieValue, bool? secureOnly = null);
}
}
3 changes: 2 additions & 1 deletion src/ServiceStack.ServiceInterface/SessionExtensions.cs
Expand Up @@ -81,7 +81,8 @@ public static string CreatePermanentSessionId(this IHttpResponse res, IHttpReque
public static string CreateTemporarySessionId(this IHttpResponse res, IHttpRequest req)
{
var sessionId = Convert.ToBase64String(Guid.NewGuid().ToByteArray());
res.Cookies.AddSessionCookie(SessionFeature.SessionId, sessionId, (EndpointHostConfig.Instance.AllowCookieSecureAsRequest && req.IsSecureConnection));
res.Cookies.AddSessionCookie(SessionFeature.SessionId, sessionId,
(EndpointHost.Config.OnlySendSessionCookiesSecurely && req.IsSecureConnection));
req.Items[SessionFeature.SessionId] = sessionId;
return sessionId;
}
Expand Down
176 changes: 87 additions & 89 deletions src/ServiceStack/ServiceHost/Cookies.cs
@@ -1,104 +1,102 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net;
using System.Text;
using System.Web;
using ServiceStack.Common.Web;

namespace ServiceStack.ServiceHost
{
public class Cookies : ICookies
{
readonly IHttpResponse httpRes;
private static readonly DateTime Session = DateTime.MinValue;
private static readonly DateTime Permanent = DateTime.UtcNow.AddYears(20);
private const string RootPath = "/";
public class Cookies : ICookies
{
readonly IHttpResponse httpRes;
private static readonly DateTime Session = DateTime.MinValue;
private static readonly DateTime Permanent = DateTime.UtcNow.AddYears(20);
private const string RootPath = "/";

public Cookies(IHttpResponse httpRes)
{
this.httpRes = httpRes;
}
public Cookies(IHttpResponse httpRes)
{
this.httpRes = httpRes;
}

/// <summary>
/// Sets a persistent cookie which never expires
/// </summary>
public void AddPermanentCookie(string cookieName, string cookieValue)
{
AddCookie(new Cookie(cookieName, cookieValue, RootPath) {
Expires = Permanent,
});
}
/// <summary>
/// Sets a persistent cookie which never expires
/// </summary>
public void AddPermanentCookie(string cookieName, string cookieValue, bool? secureOnly = null)
{
var cookie = new Cookie(cookieName, cookieValue, RootPath) {
Expires = Permanent,
};
if (secureOnly != null)
{
cookie.Secure = secureOnly.Value;
}
AddCookie(cookie);
}

/// <summary>
/// Sets a session cookie which expires after the browser session closes
/// </summary>
public void AddSessionCookie(string cookieName, string cookieValue)
{
this.AddSessionCookie(cookieName, cookieValue, false);
}
/// <summary>
/// Sets a session cookie which expires after the browser session closes
/// </summary>
public void AddSessionCookie(string cookieName, string cookieValue, bool secureCookieAsRequest)
{
var __newCookie = new Cookie(cookieName, cookieValue, RootPath);
__newCookie.Secure = secureCookieAsRequest;
this.AddCookie(__newCookie);
}
/// <summary>
/// Sets a session cookie which expires after the browser session closes
/// </summary>
public void AddSessionCookie(string cookieName, string cookieValue, bool? secureOnly = null)
{
var cookie = new Cookie(cookieName, cookieValue, RootPath);
if (secureOnly != null)
{
cookie.Secure = secureOnly.Value;
}
this.AddCookie(cookie);
}

/// <summary>
/// Deletes a specified cookie by setting its value to empty and expiration to -1 days
/// </summary>
public void DeleteCookie(string cookieName)
{
var cookie = new Cookie(cookieName, string.Empty, "/") {
Expires = DateTime.UtcNow.AddDays(-1)
};
AddCookie(cookie);
}
/// <summary>
/// Deletes a specified cookie by setting its value to empty and expiration to -1 days
/// </summary>
public void DeleteCookie(string cookieName)
{
var cookie = new Cookie(cookieName, string.Empty, "/") {
Expires = DateTime.UtcNow.AddDays(-1)
};
AddCookie(cookie);
}

public HttpCookie ToHttpCookie(Cookie cookie)
{
var httpCookie = new HttpCookie(cookie.Name, cookie.Value) {
Path = cookie.Path,
Expires = cookie.Expires,
HttpOnly = true,
Secure = cookie.Secure
};
if (string.IsNullOrEmpty(httpCookie.Domain))
{
httpCookie.Domain = (string.IsNullOrEmpty(cookie.Domain) ? null : cookie.Domain);
}
return httpCookie;
}
public HttpCookie ToHttpCookie(Cookie cookie)
{
var httpCookie = new HttpCookie(cookie.Name, cookie.Value) {
Path = cookie.Path,
Expires = cookie.Expires,
HttpOnly = true,
Secure = cookie.Secure
};
if (string.IsNullOrEmpty(httpCookie.Domain))
{
httpCookie.Domain = (string.IsNullOrEmpty(cookie.Domain) ? null : cookie.Domain);
}
return httpCookie;
}

public string GetHeaderValue(Cookie cookie)
{
return cookie.Expires == Session
? String.Format("{0}={1};path=/", cookie.Name, cookie.Value)
: String.Format("{0}={1};expires={2};path={3}",
cookie.Name, cookie.Value, cookie.Expires.ToString("R"), cookie.Path ?? "/");
}
public string GetHeaderValue(Cookie cookie)
{
return cookie.Expires == Session
? String.Format("{0}={1};path=/", cookie.Name, cookie.Value)
: String.Format("{0}={1};expires={2};path={3}",
cookie.Name, cookie.Value, cookie.Expires.ToString("R"), cookie.Path ?? "/");
}

/// <summary>
/// Sets a persistent cookie which expires after the given time
/// </summary>
public void AddCookie(Cookie cookie)
{
var aspNet = this.httpRes.OriginalResponse as HttpResponse;
if (aspNet != null)
{
var httpCookie = ToHttpCookie(cookie);
aspNet.SetCookie(httpCookie);
return;
}
var httpListener = this.httpRes.OriginalResponse as HttpListenerResponse;
if (httpListener != null)
{
var cookieStr = GetHeaderValue(cookie);
httpListener.Headers.Add(HttpHeaders.SetCookie, cookieStr);
}
}
}
/// <summary>
/// Sets a persistent cookie which expires after the given time
/// </summary>
public void AddCookie(Cookie cookie)
{
var aspNet = this.httpRes.OriginalResponse as HttpResponse;
if (aspNet != null)
{
var httpCookie = ToHttpCookie(cookie);
aspNet.SetCookie(httpCookie);
return;
}
var httpListener = this.httpRes.OriginalResponse as HttpListenerResponse;
if (httpListener != null)
{
var cookieStr = GetHeaderValue(cookie);
httpListener.Headers.Add(HttpHeaders.SetCookie, cookieStr);
}
}
}
}
13 changes: 5 additions & 8 deletions src/ServiceStack/WebHost.Endpoints/EndpointHostConfig.cs
Expand Up @@ -96,6 +96,7 @@ public static EndpointHostConfig Instance
CustomHttpHandlers = new Dictionary<HttpStatusCode, IServiceStackHttpHandler>(),
GlobalHtmlErrorHttpHandler = null,
MapExceptionToStatusCode = new Dictionary<Type, int>(),
OnlySendSessionCookiesSecurely = false,
DefaultJsonpCacheExpiration = new TimeSpan(0, 20, 0),
MetadataVisibility = EndpointAttributes.Any,
Return204NoContentForEmptyResponse = true,
Expand Down Expand Up @@ -155,6 +156,7 @@ public EndpointHostConfig()
this.CustomHttpHandlers = instance.CustomHttpHandlers;
this.GlobalHtmlErrorHttpHandler = instance.GlobalHtmlErrorHttpHandler;
this.MapExceptionToStatusCode = instance.MapExceptionToStatusCode;
this.OnlySendSessionCookiesSecurely = instance.OnlySendSessionCookiesSecurely;
this.DefaultJsonpCacheExpiration = instance.DefaultJsonpCacheExpiration;
this.MetadataVisibility = instance.MetadataVisibility;
this.Return204NoContentForEmptyResponse = Return204NoContentForEmptyResponse;
Expand Down Expand Up @@ -399,6 +401,8 @@ public EndpointAttributes MetadataVisibility
public IServiceStackHttpHandler GlobalHtmlErrorHttpHandler { get; set; }
public Dictionary<Type, int> MapExceptionToStatusCode { get; set; }

public bool OnlySendSessionCookiesSecurely { get; set; }

public TimeSpan DefaultJsonpCacheExpiration { get; set; }
public bool Return204NoContentForEmptyResponse { get; set; }

Expand All @@ -418,14 +422,7 @@ public string DefaultOperationNamespace
this.defaultOperationNamespace = value;
}
}
private const string SecureCookieAsRequest = "ss:Cookie:SecureAsRequest";
public bool AllowCookieSecureAsRequest
{
get
{
return ConfigUtils.GetAppSetting<bool>(EndpointHostConfig.SecureCookieAsRequest, false);
}
}

private string GetDefaultNamespace()
{
if (!String.IsNullOrEmpty(this.defaultOperationNamespace)
Expand Down

0 comments on commit 09a5793

Please sign in to comment.