HttpListener访问被拒绝

我正在用C#编写一个HTTP服务器。

当我尝试执行函数HttpListener.Start()我得到一个HttpListenerException

“拒绝访问”。

当我在Windows 7中以pipe理员模式运行应用程序时,它工作正常。

我可以让它运行没有pipe理模式? 如果是的话如何? 如果没有,我怎么能使应用程序开始运行后更改为pipe理模式?

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

是的,您可以在非pipe理员模式下运行HttpListener。 您只需将权限授予特定的url即可。 例如

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

文档在这里 。

我可以让它运行没有pipe理模式? 如果是的话如何? 如果没有,我怎么能使应用程序开始运行后更改为pipe理模式?

你不能,它必须以提升的特权开始。 你可以用runas动词重新启动它,这将提示用户切换到pipe理模式

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

编辑:其实,这不是真的; HttpListener可以在没有提升特权的情况下运行,但是你需要给你想要监听的URL赋予权限。 有关详细信息,请参阅Darrel Miller的答案 。

如果使用http://localhost:80/作为前缀,则可以监听http请求,而不需要pipe理权限。

语法对我来说是错误的,你必须包含引号:

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

否则我收到“参数不正确”

如果将Application Manifest添加到项目中,则可以以pipe理员身份启动应用程序。

只需将新项目添加到您的项目,然后select“应用程序清单文件”。 将<requestedExecutionLevel>元素更改为:

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

如果您想使用“user = Everyone”标志,则需要将其调整为系统语言。 用英语说就是:

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

在德国,这将是:

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

作为一个不需要提升或netsh的select,你也可以使用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); } }); } 

默认情况下,Windows定义了每个人都可以使用的以下前缀: http:// +:80 / Temporary_Listen_Addresses /

所以你可以通过以下方式注册你的HttpListener

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

这有时会导致Skype等软件默认使用端口80的问题。

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

你使用“*”,所以你执行以下cmd作为pipe理员

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

没有使用+,必须使用*,因为你spec *:4444〜。

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

我也面临类似的问题。如果你已经保留的url,那么你必须先删除url以非pipe理员模式运行,否则它将失败,访问被拒绝错误。

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