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


180

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

누군가가 그 오류를 피하려면 TcpListener로 오류를 써보십시오. 그것은 관리자 권한이 필요하지 않습니다
Vlad

나는 + 윈도우 7, 그것은이 관리자 모드에서 비주얼 스튜디오 2008 실행하는 것입니다 해결, 오류 '액세스가 거부되었습니다'생산 카운터에 비주얼 스튜디오 2008에서, 동일한 문제에 직면
마크 코르

답변:


307

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

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

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


48
이 방법은 도움이되지만이 코드 행에 지정된 URL은 완전성을 위해 명령의 URL httpListener.Prefixes.Add("http://*:4444/");과 정확히 일치해야합니다 netsh. 예를 들어, 나는 가지고 httpListener.Prefixes.Add("http://127.0.0.1:80/");있고 동일한 netsh명령을 가지고 있으며 HttpListenerException은 여전히 ​​발생합니다. 나는 변경에 필요한 httpListener.Prefixes.Add("http://+:80/");이 아웃 파악에 옳은 길에 저를 가지고 있기 때문에, 당신의 도움 @Darrel 밀러에 대한 감사합니다!
psyklopz 2016 년

10
"MyUri"가 비어 있으면 후행 슬래시를 잊지 마십시오. 그렇지 않으면 The parameter is incorrect오류가 발생합니다. 예 :url=http://+:80/
이고르 Brejc

14
관리자가 아닌 사용자 에게도이 작업을 수행 할 수있는 방법이 http://localhost:80/있습니까? 이러한 URL에서 하나의 요청을 받아야하는 데스크톱 응용 프로그램이 있는데, 관리자가이 한 가지 목적을 위해 50 개의 데스크톱에 설치해야한다는 것은 부끄러운 일입니다.
John Saunders

5
분명히 아닙니다. 설명서 페이지에는 권한 상승 또는 관리 권한에 대한 언급도 없습니다. 따라서 실제로 사용하지 않는 중대한 이유가있을 때 이것이 "더 똑똑한"TCPListener 역할을한다고 가정하기가 쉽지만 아직 문서화되어 있지는 않습니다.
David Ford

4
(; 실행은 netsh는 관리자가 필요합니다
superfly71

27

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

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

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

편집 : 실제로, 그것은 사실이 아닙니다. HttpListener는 상승 된 권한없이 실행될 수 있지만 청취하려는 URL에 대한 권한을 부여해야합니다. 자세한 내용은 Darrel Miller의 답변 을 참조하십시오.


내가 높은 권한으로 시작해야하는 이유를 설명해 주시겠습니까?
Randall Flagg

또한 'startInfo.UseShellExecute = false;'줄을 추가해야합니다. 'Process.Start (startInfo);'이전
랜달 플래그 g

@Randall : Windows가 작동하는 방식이기 때문에 프로세스가 실행되는 동안 프로세스를 관리자 모드로 전환 할 수 없습니다. UseShellExecute 관련 : 실행중인 항목에 따라 다릅니다. "notepad.exe"로 코드를 테스트
Thomas Levesque

감사. UseShellExecute 정보 : 게시 한 코드를 실행하려고했습니다. 또 다른 문제는 어떤 이유로 든 관리자 권한으로 실행하고 싶은지 묻고 그 후에는 묻지 않는 경우가 있습니다. 나는 다시 시작했다. 어떤 제안?
랜달 플래그 g

1
@Thomas 비 관리자 모드에서 HttpListener를 실행하는 데 문제가 없습니다.
Darrel Miller

23

http://localhost:80/접두사로 사용 하면 관리 권한이 없어도 http 요청을들을 수 있습니다.


2
예제 코드를 게시 할 수 있습니까? 난 그냥 이것을 시도 http://localhost:80/하고 "액세스 거부"를 얻었다.
John Saunders

2
죄송합니다. 작동하지 않는 것 같습니다. 관리자 권한으로 실행 중인지 확인하십시오. 일반적인 경우는 아닙니다.
Jonno

이것이 효과가 있다면 Windows 버그라고 생각할 것입니다. 당신이 창문에 대해 어떻게 생각하든, 나는 이것이 매우 기본적인 수준이라고 생각합니다.
hoijui

26
2 년이 지난 지금 이것은 .NET Framework 4.5가 설치된 Windows Server 2008 R2에서 작동합니다. httpListener.Prefixes.Add("http://*:4444/");실제로 Access Denied오류를 표시하지만 httpListener.Prefixes.Add("http://localhost:4444/");아무런 문제없이 작동합니다. Microsoft localhost가 이러한 제한에서 제외 된 것 같습니다 . 흥미롭게도 httpListener.Prefixes.Add("http://127.0.0.1:4444/");여전히 액세스 거부 오류가 표시되므로 작동하는 유일한 것은localhost:{any port}
Tony

1
@Tony 감사합니다. 귀하의 의견이 실제로 저에게 가장 귀중했습니다. 여러 구성에서 "127.0.0.1"이있었습니다. QA는 Windows 8.1에서 작동하지 않지만 Windows 10에서는 제대로 작동한다고보고했습니다 (Win10에서 직접 테스트했습니다). 이상하게도 Microsoft는 모든 사람이 Win10에서 127.0.0.1을 사용하도록 허가했지만 8.1 (및 이전 버전)은 사용하지 못했지만 localhost는 충분합니다. 감사합니다
Adam Plocher 2016 년

20

구문이 잘못되었습니다. 따옴표를 포함시켜야합니다.

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

그렇지 않으면 "매개 변수가 잘못되었습니다"라는 메시지가 나타납니다.


4
/URL에 후행 을 지정하지 않으면 "매개 변수가 잘못되었습니다"도 반환 될 수 있습니다.
LostSalad

13

"user = Everyone"플래그를 사용하려면 시스템 언어에 맞게 조정해야합니다. 영어로 언급 된 바와 같이 :

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

독일어로는 다음과 같습니다.

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

1
스페인어 시스템에서 : user = Todos
Rodrigo Rodrigues

또한 다른 답변에서 언급했듯이 URL을 따옴표로 묶어야했습니다.
Carsten Führmann

10

권한 상승 또는 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);
        }
    });
}

이것은 IdentityModel.OidcClient 라이브러리에 대해 IBrowser를 구현할 때 HttpListener 문제가 있었으므로 위와 매우 유사한 유스 케이스입니다.
mackie

1
위의 코드에는 버그가 있음을 주목할 가치가 있습니다. 먼저 UTF8과 함께 StreamWriter를 사용하면 일부 브라우저에서 문제가 발생합니다 .BOM 출력 등으로 인해 추측됩니다. 나는 그것을 ASCII로 바꾸었고 모든 것이 잘되었습니다. 또한 때때로 데이터를 반환하지 않으므로 스트림에서 데이터를 읽을 수있을 때까지 기다리는 코드를 추가했습니다.
mackie

감사합니다 @mackie-그 부분은 실제로 Microsoft 자체 샘플에서 직접 가져 왔습니다. 나는 그들이 실제로 제대로 테스트하지 않았다고 생각합니다. 내 답변을 편집 할 수 있다면 방법을 수정하십시오. 그렇지 않으면 변경 사항을 보내 주시면 업데이트 할 수 있습니다.
Michael Olsen

2
ASCII를 사용하는 대신 new UTF8Encoding(false)BOM 생성 을 비활성화 하는 다음 생성자를 사용해야합니다 . 나는 이미 답변에서 이것을 바꿨다
Sebastian

나는 받아 들여진 대답 보다이 솔루션을 선호합니다. netsh를 실행하면 해킹처럼 보입니다. 이것은 확실한 프로그래밍 솔루션입니다. 감사!
Jim Gomes

7

응용 프로그램 매니페스트를 프로젝트에 추가하면 응용 프로그램을 관리자로 시작할 수 있습니다.

프로젝트에 새 항목을 추가하고 "응용 프로그램 매니페스트 파일"을 선택하십시오. <requestedExecutionLevel>요소를 다음과 같이 변경하십시오 .

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

7

기본적으로 Windows는 모든 사람이 사용할 수있는 다음 접두사를 정의합니다. http : // + : 80 / Temporary_Listen_Addresses /

따라서 다음을 HttpListener통해 등록 할 수 있습니다 .

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

이로 인해 기본적으로 포트 80을 사용하려고하는 Skype와 같은 소프트웨어에 문제가 발생할 수 있습니다.


1
Skype는 범인이었습니다. 포트를 80 이 아닌 것으로 변경 했으며 작동했습니다.
고토


2

나는 또한 비슷한 문제에 직면했다. 당신이 이미 URL을 예약 한 경우 먼저 비 관리자 모드에서 실행하기 위해 URL을 삭제해야합니다. 그렇지 않으면 액세스가 거부되었습니다 오류와 함께 실패합니다.

netsh http delete urlacl url=http://+:80
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.