0

这似乎是一个基本问题,回到 Http 协议 101。但我很难理解基本身份验证的工作原理。我正在实施一个 Windows 服务,并且需要它是安全的。我想获取用户名和密码并对用户进行身份验证以访问自定义用户存储。我还想尽量减少登录调用的次数,因为登录调用代表对我们 SQL 服务器的调用。到目前为止我已经开始是这样的:

在我看来,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,这让我真正了解了身份验证方案及其工作原理。除非我准备好这个错误,否则似乎摘要方案可能能够维持“会话”或至少过期以重试我的自定义身份验证。

4

2 回答 2

4

HTTP Basic在每个请求中都需要登录凭据。HTTP 没有任何会话的概念,因此您无法真正判断某人是否“已经登录”。

于 2009-02-20T17:52:17.717 回答
0

感谢您的规范,我很感激。我确实设法解决了我的问题,它与规范无关,而是设计/托管问题。

于 2009-03-25T06:22:16.537 回答