HttpListener Access Denied

生来就可爱ヽ(ⅴ<●) 提交于 2019-11-26 01:50:42

问题


I am writing an HTTP server in C#.

When I try to execute the function HttpListener.Start() I get an HttpListenerException saying

\"Access Denied\".

When I run the app in admin mode in windows 7 it works fine.

Can I make it run without admin mode? if yes how? If not how can I make the app change to admin mode after start running?

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;
                }
            }
        }
    }
}

回答1:


Yes you can run HttpListener in non-admin mode. All you need to do is grant permissions to the particular URL. e.g.

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

Documentation is here.




回答2:


Can I make it run without admin mode? if yes how? If not how can I make the app change to admin mode after start running?

You can't, it has to start with elevated privileges. You can restart it with the runas verb, which will prompt the user to switch to admin mode

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

EDIT: actually, that's not true; HttpListener can run without elevated privileges, but you need to give permission for the URL on which you want to listen. See Darrel Miller's answer for details.




回答3:


If you use http://localhost:80/ as a prefix, you can listen to http requests with no need for Administrative privileges.




回答4:


The syntax was wrong for me, you must include the quotes:

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

otherwise I received "The parameter is incorrect"




回答5:


In case you want to use the flag "user=Everyone" you need to adjust it to your system language. In english it is as mentioned:

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

In german it would be:

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



回答6:


As an alternative that doesn't require elevation or netsh you could also use TcpListener for instance.

The following is a modified excerpt of this sample: 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

The read and write methods being:

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);
        }
    });
}



回答7:


You can start your application as administrator if you add Application Manifest to your project.

Just Add New Item to your project and select "Application Manifest File". Change the <requestedExecutionLevel> element to:

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



回答8:


By default Windows defines the following prefix that is available to everyone: http://+:80/Temporary_Listen_Addresses/

So you can register your HttpListener via:

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

This sometimes causes problems with software such as Skype which will try to utilise port 80 by default.




回答9:


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

you use "*" so you execute following cmd as admin

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

no use +, must use *, because you spec *:4444~.

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




回答10:


I also faced similar problem.If you have already reserved url then you have to first delete the url to run in non admin mode else it will fail with Access is Denied error.

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



回答11:


netsh requires Admin rights

You can fix that for localhost without admin rights by setting IgnoreWriteExceptions:

listener.IgnoreWriteExceptions = True
listener.Start()


来源:https://stackoverflow.com/questions/4019466/httplistener-access-denied

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!