web-dev-qa-db-ja.com

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;
                }
            }
        }
    }
}
152
Randall Flagg

はい、HttpListenerを非管理モードで実行できます。必要なのは、特定のURLにアクセス許可を付与することだけです。例えば.

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

ドキュメントは こちら です。

278
Darrel Miller

管理モードなしで実行できますか?はい、どうですか?そうでない場合、実行開始後にアプリを管理モードに変更するにはどうすればよいですか?

できません。昇格した権限で開始する必要があります。 runas動詞を使用して再起動できます。これにより、ユーザーに管理モードに切り替えるように求められます

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

編集:実際には、それは真実ではありません。 HttpListenerは昇格した権限なしで実行できますが、リッスンするURLにアクセス許可を与える必要があります。詳細については、 ダレルミラーの答え を参照してください。

27
Thomas Levesque

http://localhost:80/をプレフィックスとして使用すると、管理者権限を必要とせずにhttpリクエストをリッスンできます。

19
Ehsan Mirsaeedi

私にとって構文は間違っていました。引用符を含める必要があります。

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

そうでなければ、「パラメーターが正しくありません」というメッセージを受け取りました

17
Dave

フラグ「user = Everyone」を使用する場合は、システム言語に合わせて調整する必要があります。英語では、次のようになっています。

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

ドイツ語では:

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

昇格や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);
        }
    });
}
9
Michael Olsen

プロジェクトにアプリケーションマニフェストを追加すると、管理者としてアプリケーションを起動できます。

プロジェクトに新しいアイテムを追加し、「アプリケーションマニフェストファイル」を選択するだけです。 <requestedExecutionLevel>要素を次のように変更します。

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
6
R.Titov

デフォルトでは、Windowsはすべてのユーザーが使用できる次のプレフィックスを定義します。 http:// +:80/Temporary_Listen_Addresses /

したがって、次の方法でHttpListenerを登録できます。

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

これにより、デフォルトでポート80を使用しようとするSkypeなどのソフトウェアで問題が発生することがあります。

5
Sebastian
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

3
NamedStar

netshには管理者権限が必要です

IgnoreWriteExceptionsを設定することにより、管理者権限のないローカルホストの問題を修正できます。

listener.IgnoreWriteExceptions = True
listener.Start()
0
Mike Twc

私も同様の問題に直面しました。あなたがすでにURLを予約している場合は、最初に非管理モードで実行するためにURLを削除する必要があります。そうしないと、アクセスが拒否されましたエラーで失敗します.

netsh http delete urlacl url=http://+:80
0
vivek nuna