Programming

HttpListener 액세스가 거부되었습니다.

procodes 2020. 6. 4. 21:11
반응형

HttpListener 액세스가 거부되었습니다.


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

예, 비 관리자 모드에서 HttpListener를 실행할 수 있습니다. 특정 URL에 권한을 부여하기 만하면됩니다. 예 :

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

설명서는 여기에 있습니다 .


관리자 모드없이 실행할 수 있습니까? 그렇다면 어떻게? 그렇지 않은 경우 실행을 시작한 후 앱을 관리자 모드로 변경하려면 어떻게해야합니까?

높은 권한으로 시작해야합니다. runas동사를 사용하여 다시 시작하면 관리자 모드로 전환하라는 메시지가 표시됩니다.

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.


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


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"


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

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

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" />

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.


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


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

netsh requires Admin rights

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

listener.IgnoreWriteExceptions = True
listener.Start()

참고URL : https://stackoverflow.com/questions/4019466/httplistener-access-denied

반응형