httplistenerアクセスは拒否されました
-
26-09-2019 - |
質問
私はC#でHTTPサーバーを書いています。
関数を実行しようとするとき HttpListener.Start()
私は得ます HttpListenerException
言っている
"アクセスが拒否されました"。
Windows 7でAdminモードでアプリを実行すると、正常に動作します。
管理モードなしで実行することはできますか?はいの場合はどうですか?そうでない場合は、実行を開始後にアプリを管理モードに変更するにはどうすればよいですか?
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);
}
編集:実際、それは真実ではありません。 httplistenerは、特権を高めることなく実行できますが、聞きたいURLに許可を与える必要があります。見る ダレルミラーの答え 詳細については。
使用する場合 http://localhost:80/
プレフィックスとして、管理特権を必要とせずにHTTPリクエストを聞くことができます。
構文は私にとって間違っていたので、引用符を含める必要があります。
netsh http add urlacl url="http://+:4200/" user=everyone
それ以外の場合は、「パラメーターが正しくない」を受け取りました
フラグ「ユーザー=全員」を使用する場合は、システム言語に調整する必要があります。英語では、前述のとおりです。
netsh http add urlacl url=http://+:80/ user=Everyone
ドイツ語では:
netsh http add urlacl url=http://+:80/ user=Jeder
標高や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);
}
});
}
プロジェクトにアプリケーションマニフェストを追加すると、アプリケーションを管理者として開始できます。
プロジェクトに新しいアイテムを追加して、「アプリケーションマニフェストファイル」を選択するだけです。変更 <requestedExecutionLevel>
要素:
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
デフォルトでは、Windowsは誰でも利用可能な次のプレフィックスを定義します。http://+:80/companial_listen_addresses/
だからあなたはあなたを登録することができます HttpListener
経由:
Prefixes.Add("http://+:80/Temporary_Listen_Addresses/" + Guid.NewGuid().ToString("D") + "/";
これにより、デフォルトでポート80を利用しようとするSkypeなどのソフトウェアに問題が発生する場合があります。
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
また、同様の問題に直面しました。すでにURLを予約している場合、最初に非管理モードで実行するためにURLを削除する必要があります。
netsh http delete urlacl url=http://+:80
NetSHには管理者の権利が必要です
IngroreWriteExceptionsを設定することにより、管理者の権利なしでLocalHostに対してそれを修正できます。
listener.IgnoreWriteExceptions = True
listener.Start()