首页 文章

HttpListener访问被拒绝

提问于
浏览
137

我在C#中编写HTTP服务器 .

当我尝试执行函数 HttpListener.Start() 时,我得到 HttpListenerException

“访问被拒绝” .

当我在Windows 7中以管理模式运行应用程序时,它工作正常 .

我可以在没有管理员模式的情况下运行吗如果有,怎么样?如果不是,如何在开始运行后让应用程序更改为管理模式?

using System;
using System.Net;

namespace ConsoleApplication1
{
    class Program
    {
        private HttpListener httpListener = null;

        static void Main(string[] args)
        {
            Program p = new Program();
            p.Server();
        }

        public void Server()
        {
            this.httpListener = new HttpListener();

            if (httpListener.IsListening)
                throw new InvalidOperationException("Server is currently running.");

            httpListener.Prefixes.Clear();
            httpListener.Prefixes.Add("http://*:4444/");

            try
            {
                httpListener.Start(); //Throws Exception
            }
            catch (HttpListenerException ex)
            {
                if (ex.Message.Contains("Access is denied"))
                {
                    return;
                }
                else
                {
                    throw;
                }
            }
        }
    }
}

10 回答

  • 9

    我也遇到了类似的问题 . 如果你已经保留了url,那么你必须先删除url以非管理员模式运行,否则它将失败,Access is Denied错误 .

    netsh http delete urlacl url=http://+:80
    
  • 27

    是的,您可以在非管理员模式下运行HttpListener . 您需要做的就是为特定URL授予权限 . 例如

    netsh http add urlacl url=http://+:80/MyUri user=DOMAIN\user
    

    文档是here .

  • 5

    我可以在没有管理员模式的情况下运行吗?如果有,怎么样?如果不是,如何在开始运行后让应用程序更改为管理模式?

    你不能,它必须以提升的特权开始 . 您可以使用 runas 动词重新启动它,这将提示用户切换到管理模式

    static void RestartAsAdmin()
    {
        var startInfo = new ProcessStartInfo("yourApp.exe") { Verb = "runas" };
        Process.Start(startInfo);
        Environment.Exit(0);
    }
    

    编辑:实际上,那不是真的; HttpListener可以在没有提升权限的情况下运行,但您需要为要监听的URL授予权限 . 有关详细信息,请参阅Darrel Miller's answer .

  • 17

    如果使用 http://localhost:80/ 作为前缀,则可以在不需要管理权限的情况下侦听http请求 .

  • 8

    语法对我来说是错误的,你必须包括引号:

    netsh http add urlacl url="http://+:4200/" user=everyone
    

    否则我收到“参数不正确”

  • 5

    如果您想使用“user = Everyone”标志,您需要将其调整为您的系统语言 . 在英语中如上所述:

    netsh http add urlacl url=http://+:80/ user=Everyone
    

    在德国,它将是:

    netsh http add urlacl url=http://+:80/ user=Jeder
    
  • 1

    作为不需要提升或netsh的替代方法,您也可以使用TcpListener .

    以下是此示例的修改摘录:https://github.com/googlesamples/oauth-apps-for-windows/tree/master/OAuthDesktopApp

    // Generates state and PKCE values.
    string state = randomDataBase64url(32);
    string code_verifier = randomDataBase64url(32);
    string code_challenge = base64urlencodeNoPadding(sha256(code_verifier));
    const string code_challenge_method = "S256";
    
    // Creates a redirect URI using an available port on the loopback address.
    var listener = new TcpListener(IPAddress.Loopback, 0);
    listener.Start();
    string redirectURI = string.Format("http://{0}:{1}/", IPAddress.Loopback, ((IPEndPoint)listener.LocalEndpoint).Port);
    output("redirect URI: " + redirectURI);
    
    // Creates the OAuth 2.0 authorization request.
    string authorizationRequest = string.Format("{0}?response_type=code&scope=openid%20profile&redirect_uri={1}&client_id={2}&state={3}&code_challenge={4}&code_challenge_method={5}",
        authorizationEndpoint,
        System.Uri.EscapeDataString(redirectURI),
        clientID,
        state,
        code_challenge,
        code_challenge_method);
    
    // Opens request in the browser.
    System.Diagnostics.Process.Start(authorizationRequest);
    
    // Waits for the OAuth authorization response.
    var client = await listener.AcceptTcpClientAsync();
    
    // Read response.
    var response = ReadString(client);
    
    // Brings this app back to the foreground.
    this.Activate();
    
    // Sends an HTTP response to the browser.
    WriteStringAsync(client, "<html><head><meta http-equiv='refresh' content='10;url=https://google.com'></head><body>Please close this window and return to the app.</body></html>").ContinueWith(t =>
    {
        client.Dispose();
        listener.Stop();
    
        Console.WriteLine("HTTP server stopped.");
    });
    
    // TODO: Check the response here to get the authorization code and verify the code challenge
    

    读写方法是:

    private string ReadString(TcpClient client)
    {
        var readBuffer = new byte[client.ReceiveBufferSize];
        string fullServerReply = null;
    
        using (var inStream = new MemoryStream())
        {
            var stream = client.GetStream();
    
            while (stream.DataAvailable)
            {
                var numberOfBytesRead = stream.Read(readBuffer, 0, readBuffer.Length);
                if (numberOfBytesRead <= 0)
                    break;
    
                inStream.Write(readBuffer, 0, numberOfBytesRead);
            }
    
            fullServerReply = Encoding.UTF8.GetString(inStream.ToArray());
        }
    
        return fullServerReply;
    }
    
    private Task WriteStringAsync(TcpClient client, string str)
    {
        return Task.Run(() =>
        {
            using (var writer = new StreamWriter(client.GetStream(), new UTF8Encoding(false)))
            {
                writer.Write("HTTP/1.0 200 OK");
                writer.Write(Environment.NewLine);
                writer.Write("Content-Type: text/html; charset=UTF-8");
                writer.Write(Environment.NewLine);
                writer.Write("Content-Length: " + str.Length);
                writer.Write(Environment.NewLine);
                writer.Write(Environment.NewLine);
                writer.Write(str);
            }
        });
    }
    
  • 14

    如果将Application Manifest添加到项目中,则可以以管理员身份启动应用程序 .

    只需将新项添加到项目中,然后选择"Application Manifest File" . 将 <requestedExecutionLevel> 元素更改为:

    <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
    
  • 0

    默认情况下,Windows定义以下每个人都可用的前缀:http://+:80/Temporary_Listen_Addresses/

    所以你可以通过以下方式注册你的 HttpListener

    Prefixes.Add("http://+:80/Temporary_Listen_Addresses/" + Guid.NewGuid().ToString("D") + "/";

    这有时会导致Skype等软件出现问题,默认情况下会尝试使用端口80 .

  • 255
    httpListener.Prefixes.Add("http://*:4444/");
    

    您使用“*”,因此您执行以下cmd作为管理员

    netsh http add urlacl url=http://*:4444/ user=username
    

    没用,必须使用*,因为你的规格*:4444~ .

    https://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx

相关问题