2009-02-20 117 views
0

这可能看起来像一个基本的问题,并回到Http协议101.但我很难理解基本身份验证的工作原理。我正在实施一个Windows服务,并且需要它是安全的。我想获取用户名和密码,并将用户身份验证到自定义用户商店。我还希望最小化登录调用的次数,因为登录调用表示对我们的SQL服务器的调用。到目前为止我开始的是这样的:基本身份验证在处理HttpListener时如何工作?

我看到它的方式UserAuthorized函数必须使我的自定义登录电话。但是,我不想每次都这样做。如果您已登录,基本身份验证是否会保留,或者是否存在我应该探索的缓存线程安全解决方案。

噢,我也想这样做,以便当用户进行身份验证和对象被创建并维护在线程中供侦听器引用用户/连接的后续回调。但由于ListenerCallback是静态的,我不确定这是如何实现的。

在此先感谢您的帮助,我真的很感激它和StackOverflow。

public void ThreadProc() { 
    string uriPrefix = ConfigurationManager.AppSettings["ListenerPrefix"]; 
    HttpListener listener = new HttpListener(); 
    listener.Prefixes.Add(uriPrefix); 
    listener.AuthenticationSchemes = AuthenticationSchemes.Basic; 

    listener.Start(); 

    Console.WriteLine("Start listening on " + uriPrefix); 
    Console.WriteLine("Press Control-C to stop listener..."); 

    while (listening) { 
     IAsyncResult result = listener.BeginGetContext(new AsyncCallback(ListenerCallback), listener); 
     result.AsyncWaitHandle.WaitOne(); 
    } 
} 

public static void ListenerCallback(IAsyncResult result) { 
    HttpListener listener = (HttpListener)result.AsyncState; 
    HttpListenerContext context = listener.EndGetContext(result); 
    WebDavEngine engine = new WebDavEngine(context.User); 

    context.Response.SendChunked = false; 
    FileLogger.Level = LogLevel.Debug; 

    engine.IgnoreExceptions = false; 

    if (UserAutorized(context)) { 
     try { 
      engine.Run(context, listener.Prefixes); 
      engine.CommitTransaction(); 
     } catch { 
      engine.RollBackTransaction(); 
     } finally { 
      engine.CloseConnection(); 
     } 
    } else 
     context.Response.StatusCode = 401; 

    if (context.Response.StatusCode == 401) 
     ShowLoginDialog(context, context.Response); 

    try { 
     context.Response.Close(); 
    } catch { 
     // client closed connection before the content was sent 
    } 
} 

private static bool UserAutorized(HttpListenerContext context) { 
    HttpListenerBasicIdentity identity = (HttpListenerBasicIdentity)context.User.Identity; 

    if (!identity.IsAuthenticated) { 
     string username = identity.Name; 

     // workaround for Windows Vista Basic authentication. User name may be submitted in the following format: Machine\User. 
     int ind = username.LastIndexOf('\\'); 
     if (ind > 0) 
      username = username.Remove(0, ind + 1); 


     Console.WriteLine("Trying Authentication since identity is NOT authenticated"); 

     return false; 
    } else { 
     Console.WriteLine("identity.IsAuthenticated: " + identity.IsAuthenticated.ToString()); 
     return identity.IsAuthenticated; 
    }    
} 

编辑: +1单独的文件,真正睁开眼睛的身份验证方案的美服以及它们如何工作。除非我准备好了这个错误,否则Digest方案似乎可能会维持一个“会话”或至少过期以重试我的自定义身份验证。

回答

0

感谢您的规范,我赞赏它。我设法解决了我的问题,它不是与规格相关的,而是设计/托管问题。

4

HTTP Basic需要每个请求的登录凭证。 HTTP没有会话的任何概念,所以你不能真正知道某人是否“已经登录”。