Instantly share code, notes, and snippets.
Created
February 17, 2012 09:36
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save chgeuer/1852178 to your computer and use it in GitHub Desktop.
Silverlight password cookie and testing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.ObjectModel; | |
using System.Linq; | |
using System.Net; | |
using System.Security; | |
using System.Security.Principal; | |
using System.ServiceModel; | |
using System.ServiceModel.Channels; | |
using System.ServiceModel.Description; | |
using System.ServiceModel.Dispatcher; | |
using System.Threading; | |
/* | |
* C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.ServiceModel.dll | |
* C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.ServiceModel.dll | |
*/ | |
namespace ConsoleApplication1 | |
{ | |
class WCF_Silverlight_Cookie_Tester | |
{ | |
static void Main(string[] args) | |
{ | |
var logonAddress = "http://localhost/Logon"; | |
var regularServiceAddress = "http://localhost/OtherService"; | |
#region Bring up services | |
var logonServiceHost = new ServiceHost(typeof(LogonServiceImpl)); | |
logonServiceHost.Description.Behaviors.Add(new CookieGenerationBehavior()); | |
logonServiceHost.Description.Behaviors.Find<ServiceDebugBehavior>().IncludeExceptionDetailInFaults = true; | |
logonServiceHost.AddServiceEndpoint(typeof(ILogonService), new BasicHttpBinding(), (logonAddress)); | |
logonServiceHost.Open(); | |
var otherServiceHost = new ServiceHost(typeof (SomeOtherServiceImpl)); | |
otherServiceHost.Description.Behaviors.Add(new CookieGenerationBehavior()); | |
otherServiceHost.Description.Behaviors.Find<ServiceDebugBehavior>().IncludeExceptionDetailInFaults = true; | |
otherServiceHost.AddServiceEndpoint(typeof(ISomeOtherService), new BasicHttpBinding(), (regularServiceAddress)); | |
otherServiceHost.Open(); | |
#endregion | |
// var cookieStore = new CookieStore(/*"Christian", "Christian", logonAddress*/); | |
var cookieStore = new CookieStore(); | |
try | |
{ | |
var logonChannelFactory = new ChannelFactory<ILogonService>(new BasicHttpBinding()); | |
logonChannelFactory.Endpoint.Behaviors.Add(new ClientCookieFetchBehavior(cookieStore, ServiceType.Logon)); | |
var logonClient = logonChannelFactory.CreateChannel(new EndpointAddress(logonAddress)); | |
logonClient.Logon("Christian", "Christian"); | |
var serviceChannelFactory = new ChannelFactory<ISomeOtherService>(new BasicHttpBinding()); | |
serviceChannelFactory.Endpoint.Behaviors.Add(new ClientCookieFetchBehavior(cookieStore, ServiceType.Regular)); | |
var service = serviceChannelFactory.CreateChannel(new EndpointAddress(regularServiceAddress)); | |
Console.WriteLine("Service says: {0}", service.DoStuff("Hello world")); | |
} | |
finally | |
{ | |
#region Shutdown services | |
otherServiceHost.Close(); | |
logonServiceHost.Close(); | |
#endregion | |
} | |
} | |
} | |
#region Client side | |
[ServiceContract] | |
public interface ILogonService | |
{ | |
[OperationContract] | |
bool Logon(string username, string password); | |
} | |
[ServiceContract] | |
public interface ISomeOtherService | |
{ | |
[OperationContract] | |
string DoStuff(string input); | |
} | |
public class LogonException : Exception | |
{ | |
public LogonException(string message) : base(message) { } | |
} | |
public class ClientCookieFetchBehavior : IEndpointBehavior | |
{ | |
internal ClientCookieFetchBehavior(CookieStore cookieStore, ServiceType serviceType) | |
{ | |
this.CookieStore = cookieStore; | |
this.ServiceType = serviceType; | |
} | |
public CookieStore CookieStore { get; set; } | |
private ServiceType ServiceType { get; set; } | |
#region IEndpointBehavior members | |
void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) | |
{ | |
clientRuntime.MessageInspectors.Add(new LogonCookieRetrievalMessageInspector(this.CookieStore, this.ServiceType)); | |
} | |
void IEndpointBehavior.AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } | |
void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { } | |
void IEndpointBehavior.Validate(ServiceEndpoint endpoint) { } | |
#endregion | |
} | |
#endregion | |
#region Service side | |
public class LogonServiceImpl : ILogonService | |
{ | |
bool ILogonService.Logon(string username, string password) | |
{ | |
if (username != password) | |
{ | |
return false; | |
} | |
Thread.CurrentPrincipal = new MyPrincipal(username); | |
return true; | |
} | |
} | |
public class SomeOtherServiceImpl : ISomeOtherService | |
{ | |
string ISomeOtherService.DoStuff(string input) | |
{ | |
var principal = Thread.CurrentPrincipal as MyPrincipal; | |
if (principal == null) | |
{ | |
throw new SecurityException("Unauthenticated"); | |
} | |
return string.Format("{0} receives {1}", principal.Name, input); | |
} | |
} | |
public class CookieGenerationBehavior : IServiceBehavior | |
{ | |
void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) | |
{ | |
serviceDescription.Endpoints.ToList().ForEach(endpoint => endpoint.Behaviors.Add(new CookieGeneratorEndpointBehavior())); | |
} | |
void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { } | |
void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } | |
} | |
public class CookieGeneratorEndpointBehavior : IEndpointBehavior | |
{ | |
#region IEndpointBehavior members | |
void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { } | |
void IEndpointBehavior.AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } | |
void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) | |
{ | |
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new LogonCookieGenerationMessageInspector()); | |
} | |
void IEndpointBehavior.Validate(ServiceEndpoint endpoint) { } | |
#endregion | |
} | |
internal class MyPrincipal : IPrincipal | |
{ | |
public MyPrincipal(string name) | |
{ | |
_identity = new MyIdentity { Name = name }; | |
} | |
private IIdentity _identity; | |
public string Name { get { return _identity.Name; } } | |
IIdentity IPrincipal.Identity | |
{ | |
get { return _identity; } | |
} | |
bool IPrincipal.IsInRole(string role) | |
{ | |
throw new NotImplementedException(); | |
} | |
} | |
internal class MyIdentity : IIdentity | |
{ | |
string IIdentity.AuthenticationType | |
{ | |
get { return ""; } | |
} | |
bool IIdentity.IsAuthenticated | |
{ | |
get { return true; } | |
} | |
public string Name { get; set; } | |
} | |
#endregion | |
public class CookieStore | |
{ | |
public CookieStore() { } | |
//public CookieStore(string username, string password, string service) | |
//{ | |
// Username = username; | |
// Password = password; | |
// Service = service; | |
// IsLoggedIn = false; | |
//} | |
// | |
//public string Username { get; private set; } | |
//public string Password { get; private set; } | |
//public string Service { get; private set; } | |
//public bool IsLoggedIn { get; private set; } | |
// | |
//private object _logonLock = new object(); | |
//private void Logon() | |
//{ | |
// if (!IsLoggedIn) | |
// { | |
// var logonChannelFactory = new ChannelFactory<ILogonService>(new BasicHttpBinding()); | |
// this.EmulateInternetExplorerCookieHandlingForLogon(logonChannelFactory); | |
// var logon = logonChannelFactory.CreateChannel(new EndpointAddress(Service)); | |
// var success = logon.Logon(Username, Password); | |
// | |
// if (!success) | |
// throw new LogonException("Could not logon"); | |
// } | |
// IsLoggedIn = true; | |
//} | |
public string Cookie | |
{ | |
get | |
{ | |
//if (_cookieValue == null && !string.IsNullOrEmpty(this.Username) ) | |
//{ | |
// lock (_logonLock) | |
// { | |
// if (_cookieValue == null && !string.IsNullOrEmpty(this.Username)) | |
// { | |
// Logon(); | |
// } | |
// } | |
//} | |
return _cookieValue; | |
} | |
} | |
public void SetCookieValue(string value) | |
{ | |
_cookieValue = value; | |
} | |
private string _cookieValue; | |
public void EmulateInternetExplorerCookieHandling(ChannelFactory cf) | |
{ | |
cf.Endpoint.Behaviors.Add(new ClientCookieFetchBehavior(this, ServiceType.Regular)); | |
} | |
public void EmulateInternetExplorerCookieHandlingForLogon(ChannelFactory cf) | |
{ | |
cf.Endpoint.Behaviors.Add(new ClientCookieFetchBehavior(this, ServiceType.Logon)); | |
} | |
} | |
internal enum ServiceType | |
{ | |
Logon, | |
Regular | |
} | |
internal class LogonCookieRetrievalMessageInspector : IClientMessageInspector | |
{ | |
public CookieStore CookieStore { get; set; } | |
internal ServiceType ServiceType { get; set; } | |
private LogonCookieRetrievalMessageInspector() { } | |
internal LogonCookieRetrievalMessageInspector(CookieStore cookieStore, ServiceType serviceType) | |
{ | |
this.CookieStore = cookieStore; | |
this.ServiceType = serviceType; | |
} | |
private const string SET_COOKIE = "Set-Cookie"; | |
#region IClientMessageInspector | |
object IClientMessageInspector.BeforeSendRequest(ref Message request, IClientChannel channel) | |
{ | |
if (this.ServiceType == ServiceType.Logon) | |
{ | |
return null; | |
} | |
HttpRequestMessageProperty httpRequestMessage; | |
object httpRequestMessageObject; | |
if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out httpRequestMessageObject)) | |
{ | |
httpRequestMessage = (HttpRequestMessageProperty)httpRequestMessageObject; | |
} | |
else | |
{ | |
httpRequestMessage = new HttpRequestMessageProperty(); | |
request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage); | |
} | |
httpRequestMessage.Headers[SET_COOKIE] = this.CookieStore.Cookie; | |
//var cookieContainer = new CookieContainer(); | |
//channel.GetProperty<IHttpCookieContainerManager>().CookieContainer = cookieContainer; | |
return null; | |
} | |
void IClientMessageInspector.AfterReceiveReply(ref Message reply, object correlationState) | |
{ | |
HttpResponseMessageProperty httpResponseMessage; | |
object httpRequestMessageObject; | |
if (reply.Properties.TryGetValue(HttpResponseMessageProperty.Name, out httpRequestMessageObject)) | |
{ | |
httpResponseMessage = (HttpResponseMessageProperty)httpRequestMessageObject; | |
var value = httpResponseMessage.Headers[SET_COOKIE]; | |
this.CookieStore.SetCookieValue(value); | |
} | |
} | |
#endregion | |
} | |
internal class LogonCookieGenerationMessageInspector : IDispatchMessageInspector | |
{ | |
private const string SET_COOKIE = "Set-Cookie"; | |
object IDispatchMessageInspector.AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) | |
{ | |
return null; | |
} | |
void IDispatchMessageInspector.BeforeSendReply(ref Message reply, object correlationState) | |
{ | |
var principal = Thread.CurrentPrincipal as MyPrincipal; | |
if (principal == null) | |
{ | |
return; | |
} | |
HttpResponseMessageProperty httpResponseMessage; | |
object httpRequestMessageObject; | |
if (reply.Properties.TryGetValue(HttpResponseMessageProperty.Name, out httpRequestMessageObject)) | |
{ | |
httpResponseMessage = (HttpResponseMessageProperty)httpRequestMessageObject; | |
} | |
else | |
{ | |
httpResponseMessage = new HttpResponseMessageProperty(); | |
reply.Properties.Add(HttpResponseMessageProperty.Name, httpResponseMessage); | |
} | |
httpResponseMessage.Headers[SET_COOKIE] = principal.Name; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment