Accès À HttpListener Refusé
j'écris un serveur HTTP en C#.
quand j'essaie d'exécuter la fonction HttpListener.Start()
j'obtiens un HttpListenerException
disant
"Accès Refusé".
quand j'exécute l'application en mode administrateur dans windows 7 Il fonctionne très bien.
puis-je le faire fonctionner sans mode administrateur? si oui, comment? Si ce n'est pas le cas, comment puis-je faire changer l'application en mode administrateur après avoir démarré l'application?
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;
}
}
}
}
}
10 réponses
Oui vous pouvez exécuter HttpListener en mode non-administrateur. Tout ce que vous devez faire est d'accorder des permissions à L'URL particulière. par exemple
netsh http add urlacl url=http://+:80/MyUri user=DOMAIN\user
Documentation est ici .
puis-je le faire fonctionner sans mode administrateur? si oui, comment? Si ce n'est pas le cas, comment puis-je faire changer l'application en mode administrateur après avoir démarré l'application?
vous ne pouvez pas, il faut commencer avec des privilèges élevés. Vous pouvez le redémarrer avec le verbe runas
, qui invite l'utilisateur à passer en mode administrateur
static void RestartAsAdmin()
{
var startInfo = new ProcessStartInfo("yourApp.exe") { Verb = "runas" };
Process.Start(startInfo);
Environment.Exit(0);
}
EDIT: en fait, ce n'est pas vrai; HttpListener peut courir sans privilèges élevés, mais vous devez donner la permission pour L'URL sur laquelle vous voulez écouter. Voir réponse de Darrel Miller pour plus de détails.
si vous utilisez http://localhost:80/
comme préfixe, Vous pouvez écouter des requêtes http sans avoir besoin de privilèges administratifs.
la syntaxe était fausse pour moi, vous devez inclure les citations:
netsh http add urlacl url="http://+:4200/" user=everyone
sinon j'ai reçu "le paramètre est incorrect "
dans le cas où vous voulez utiliser le drapeau" user=Everyone " vous devez l'ajuster à votre langage système. En anglais, il est comme il est mentionné:
netsh http add urlacl url=http://+:80/ user=Everyone
en allemand ce serait:
netsh http add urlacl url=http://+:80/ user=Jeder
comme alternative qui ne nécessite pas d'élévation ou netsh, vous pouvez également utiliser TcpListener par exemple.
l'extrait suivant est un extrait modifié de cet échantillon.: 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
les méthodes de lecture et d'écriture étant:
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);
}
});
}
vous pouvez démarrer votre application en tant qu'administrateur si vous ajoutez le Manifeste D'Application à votre projet.
il suffit d'Ajouter un nouvel élément à votre projet et sélectionnez"application Manifest File". Remplacer l'élément <requestedExecutionLevel>
par:
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
Par Défaut Windows définit le préfixe suivant qui est disponible pour tout le monde: http://+: 80 / Temporary_Listen_Addresses/
pour que vous puissiez enregistrer votre HttpListener
via:
Prefixes.Add("http://+:80/Temporary_Listen_Addresses/" + Guid.NewGuid().ToString("D") + "/";
cela cause parfois des problèmes avec des logiciels tels que Skype qui vont essayer d'utiliser le port 80 par défaut.
httpListener.Prefixes.Add("http://*:4444/");
vous utilisez " * "alors vous exécutez cmd suivant comme administrateur
netsh http add urlacl url=http://*:4444/ user=username
pas d'utilisation +, doit utiliser *, parce que vous spec *:4444~.
https://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx
j'ai également fait face à un problème similaire.Si vous avez déjà réservé url alors vous devez d'abord supprimer l'url à exécuter en mode non administrateur sinon il échouera avec L'accès est refusé erreur.
netsh http delete urlacl url=http://+:80