Przeglądaj źródła

HTTP authentication in HttpListener had dropped during refactoring. Now it's back.

Atsushi Eno 15 lat temu
rodzic
commit
1fe37c584d

+ 1 - 1
mcs/class/System.ServiceModel/System.ServiceModel.Channels.Http/HttpChannelListener.cs

@@ -127,7 +127,7 @@ namespace System.ServiceModel.Channels.Http
 		{
 			listener_manager = GetOrCreateListenerManager ();
 			Properties.Add (listener_manager);
-			listener_manager.RegisterListener (ChannelDispatcher, timeout);
+			listener_manager.RegisterListener (ChannelDispatcher, Source, timeout);
 		}
 
 		protected override void OnAbort ()

+ 12 - 3
mcs/class/System.ServiceModel/System.ServiceModel.Channels.Http/HttpListenerManager.cs

@@ -50,7 +50,7 @@ namespace System.ServiceModel.Channels.Http
 
 		public List<HttpChannelListenerEntry> Entries { get; private set; }
 
-		public abstract void RegisterListener (ChannelDispatcher channel, TimeSpan timeout);
+		public abstract void RegisterListener (ChannelDispatcher channel, HttpTransportBindingElement element, TimeSpan timeout);
 		public abstract void UnregisterListener (ChannelDispatcher channel, TimeSpan timeout);
 
 		protected void RegisterListenerCommon (ChannelDispatcher channel, TimeSpan timeout)
@@ -125,13 +125,22 @@ namespace System.ServiceModel.Channels.Http
 		Thread loop;
 
 		// FIXME: use timeout
-		public override void RegisterListener (ChannelDispatcher channel, TimeSpan timeout)
+		public override void RegisterListener (ChannelDispatcher channel, HttpTransportBindingElement element, TimeSpan timeout)
 		{
 			RegisterListenerCommon (channel, timeout);
 
 			if (Entries.Count != 1)
 				return;
 
+			if (element != null) {
+				var l = listener;
+				l.AuthenticationSchemeSelectorDelegate = delegate (HttpListenerRequest req) {
+					return element.AuthenticationScheme;
+				};
+				l.Realm = element.Realm;
+				l.UnsafeConnectionNtlmAuthentication = element.UnsafeConnectionNtlmAuthentication;
+			}
+
 			// Start here. It is shared between channel listeners
 			// that share the same listen Uri. So there is no other appropriate place.
 #if USE_SEPARATE_LOOP // this cannot be enabled because it causes infinite loop when ChannelDispatcher is not involved.
@@ -190,7 +199,7 @@ namespace System.ServiceModel.Channels.Http
 		{
 		}
 
-		public override void RegisterListener (ChannelDispatcher channel, TimeSpan timeout)
+		public override void RegisterListener (ChannelDispatcher channel, HttpTransportBindingElement element, TimeSpan timeout)
 		{
 			RegisterListenerCommon (channel, timeout);
 		}

+ 23 - 0
mcs/class/System.ServiceModel/System.ServiceModel.Channels.Http/HttpReplyChannel.cs

@@ -28,9 +28,12 @@
 using System;
 using System.Collections.Generic;
 using System.Collections.Specialized;
+using System.IdentityModel.Selectors;
+using System.IdentityModel.Tokens;
 using System.IO;
 using System.Net;
 using System.ServiceModel;
+using System.ServiceModel.Security;
 using System.Text;
 using System.Threading;
 
@@ -40,11 +43,18 @@ namespace System.ServiceModel.Channels.Http
 	{
 		HttpChannelListener<IReplyChannel> source;
 		RequestContext reqctx;
+		SecurityTokenAuthenticator security_token_authenticator;
+		SecurityTokenResolver security_token_resolver;
 
 		public HttpReplyChannel (HttpChannelListener<IReplyChannel> listener)
 			: base (listener)
 		{
 			this.source = listener;
+
+			if (listener.SecurityTokenManager != null) {
+				var str = new SecurityTokenRequirement () { TokenType = SecurityTokenTypes.UserName };
+				security_token_authenticator = listener.SecurityTokenManager.CreateSecurityTokenAuthenticator (str, out security_token_resolver);
+			}
 		}
 
 		public MessageEncoder Encoder {
@@ -139,6 +149,19 @@ namespace System.ServiceModel.Channels.Http
 			if (ctxi == null)
 				return true; // returning true, yet context is null. This happens at closing phase.
 
+			if (source.Source.AuthenticationScheme != AuthenticationSchemes.Anonymous) {
+				if (security_token_authenticator != null)
+					// FIXME: use return value?
+					try {
+						security_token_authenticator.ValidateToken (new UserNameSecurityToken (ctxi.User, ctxi.Password));
+					} catch (Exception) {
+						ctxi.ReturnUnauthorized ();
+					}
+				else {
+					ctxi.ReturnUnauthorized ();
+				}
+			}
+
 			Message msg = null;
 
 			if (ctxi.Request.HttpMethod == "POST") {