HttpListener एक्सेस अस्वीकृत


180

मैं C # में एक HTTP सर्वर लिख रहा हूँ।

जब मैं फ़ंक्शन को निष्पादित करने का प्रयास करता HttpListener.Start()हूं तो मुझे एक HttpListenerExceptionकहावत मिलती है

"पहुंच अस्वीकृत"।

जब मैं विंडोज़ 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 के साथ लिखने की कोशिश कर सकता है। इसके लिए व्यवस्थापक विशेषाधिकारों की आवश्यकता नहीं है
व्लाद

मैं एक ही मुद्दे का सामना करता हूं, विजुअल स्टूडियो 2008 + विंडोज 7 में, यह 'एक्सेस अस्वीकृत' त्रुटि उत्पन्न करता है, इसका समाधान करने के लिए यह है कि विजुअल स्टूडियो 2008 को एडमिन मोड में चलाएं
मार्क खोर

जवाबों:


307

हाँ, आप गैर-व्यवस्थापक मोड में HttpListener चला सकते हैं। आपको केवल विशेष URL के लिए अनुमतियाँ प्रदान करने की आवश्यकता है। जैसे

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

प्रलेखन यहाँ है


48
यह सहायक है, लेकिन पूर्णता के लिए, कोड की इस पंक्ति में निर्दिष्ट URL: आदेश httpListener.Prefixes.Add("http://*:4444/");में एक के साथ सटीक रूप से मेल खाना चाहिए netsh। उदाहरण के लिए, मेरे पास httpListener.Prefixes.Add("http://127.0.0.1:80/");और netshआपके पास वही कमांड है, और HttpListenerException अभी भी फेंक दी जाएगी। मुझे httpListener.Prefixes.Add("http://+:80/");आपकी मदद के लिए धन्यवाद बदलने की जरूरत थी @Drelrel मिलर, क्योंकि आपने मुझे इस बात का पता लगाने के लिए सही रास्ते पर ले लिया!
सायक्लोपेज़

10
और यदि "MyUri" खाली है तो ट्रेलिंग स्लैश को न भूलें, अन्यथा आपको एक The parameter is incorrectत्रुटि मिलेगी । उदाहरण:url=http://+:80/
इगोर ब्रेजक

14
क्या गैर-प्रशासनिक उपयोगकर्ता के लिए भी ऐसा करने का कोई तरीका है http://localhost:80/? मेरे पास एक डेस्कटॉप एप्लिकेशन है जिसे ऐसे URL पर एक अनुरोध प्राप्त करने की आवश्यकता है, और इसके लिए शर्म की बात है कि एक प्रशासक ने इसे केवल एक उद्देश्य के लिए 50 डेस्कटॉप पर स्थापित किया है।
जॉन सॉन्डर्स

5
जाहिरा तौर पर नहीं। प्रलेखन पृष्ठ में आवश्यक ऊंचाई या प्रशासनिक विशेषाधिकारों का कोई उल्लेख नहीं है। इसलिए यह मान लेना आसान है कि यह "स्मार्ट" टीसीएलस्टनर के रूप में कार्य करेगा, जब वास्तव में इसका उपयोग न करने का प्रमुख कारण है - फिर भी यह दस्तावेज नहीं है।
डेविड फोर्ड

4
रनिंग नेट्स के लिए व्यवस्थापक की आवश्यकता होती है; (
superfly71

27

क्या मैं इसे बिना व्यवस्थापक मोड के चला सकता हूं? यदि हाँ तो कैसे? यदि नहीं, तो मैं कैसे शुरू करने के बाद ऐप को एडमिन मोड में बदल सकता हूं?

आप इसे विशेषाधिकारों के साथ शुरू नहीं कर सकते। आप इसे runasक्रिया के साथ पुनरारंभ कर सकते हैं , जो उपयोगकर्ता को व्यवस्थापक मोड पर स्विच करने के लिए संकेत देगा

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

संपादित करें: वास्तव में, यह सच नहीं है; HttpListener उन्नत विशेषाधिकार के बिना चल सकता है, लेकिन आपको उस URL की अनुमति देने की आवश्यकता है जिस पर आप सुनना चाहते हैं। देखें डेरेल मिलर जवाब जानकारी के लिए।


क्या आप कृपया बता सकते हैं कि मुझे उन्नत विशेषाधिकार के साथ शुरुआत क्यों करनी है?
रैंडाल फ्लैग

आपको यह पंक्ति 'startInfo.UseShellExecute = false;' भी जोड़ने की आवश्यकता है पहले 'Process.Start (startInfo);'
रान्डेल फ्लैग

@ रैंडल: क्योंकि विंडोज कैसे काम करता है ... एक प्रक्रिया चल रही है, जबकि व्यवस्थापक मोड पर स्विच नहीं कर सकता। UseShellExecute के बारे में: यह उस पर निर्भर करता है जो आप निष्पादित कर रहे हैं। मैंने "notepad.exe" के साथ अपने कोड का परीक्षण किया, यह UseShellExecute = false के बिना ठीक काम करता है
थॉमस लेवेस्क

धन्यवाद। UseShellExecute के बारे में: मैंने अपने द्वारा पोस्ट किए गए कोड को चलाने का प्रयास किया। एक और समस्या यह है कि किसी कारण से इसने मुझसे एक बार पूछा कि क्या मैं प्रशासक के रूप में चलना चाहता हूं और उसके बाद किसी भी समय यह नहीं पूछता है। मैंने पुनः आरंभ किया, यह सुनिश्चित करने के लिए डिबग किया कि यह वहां जाता है और कुछ भी नहीं। कोई सुझाव?
रान्डेल फ्लैग

1
@Thomas गैर-व्यवस्थापक मोड में HttpListener को चलाने में कोई समस्या नहीं है।
डारेल मिलर

23

यदि आप http://localhost:80/उपसर्ग के रूप में उपयोग करते हैं , तो आप प्रशासनिक विशेषाधिकारों की आवश्यकता के बिना http अनुरोधों को सुन सकते हैं।


2
क्या आप कुछ उदाहरण कोड पोस्ट कर सकते हैं? मैंने बस इसके साथ प्रयास किया http://localhost:80/और "एक्सेस डेनिड" प्राप्त किया।
जॉन सॉन्डर्स

2
क्षमा करें, यह काम नहीं करता है। कृपया जाँचें कि क्या आप व्यवस्थापक के रूप में चल रहे हैं, जो सामान्य मामला नहीं होना चाहिए।
जोनो

अगर यह काम करेगा, मैं इसे एक विंडोज़ बग पर विचार करूंगा। कोई फर्क नहीं पड़ता कि आप खिड़कियों के बारे में क्या सोचते हैं, मैं इसे बहुत बुनियादी स्तर का मानता हूं कि बहुत, बहुत संभव है कि वे सही ढंग से संभालने में चूक नहीं गए।
होइजुई

26
तो 2 साल से अधिक समय बाद, यह मेरे लिए अब विंडोज सर्वर 2008 R2 पर .NET फ्रेमवर्क 4.5 के साथ काम करता है। 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}
टोनी

1
@ धन्यवाद आपकी टिप्पणी वास्तव में मेरे लिए सबसे मूल्यवान थी। मेरे पास कई कॉन्फिग्स में "127.0.0.1" था। क्यूए ने बताया कि यह विंडोज 8.1 पर काम नहीं कर रहा था, लेकिन विंडोज 10 में ठीक था (और मैंने इसे Win10 में खुद परखा)। अजीब तरह से, ऐसा लगता है कि Microsoft ने Win10 में सभी को 127.0.0.1 का उपयोग करने की अनुमति दी है, लेकिन 8.1 नहीं (और संभवतः पूर्व संस्करणों), लेकिन निश्चित रूप से पर्याप्त है, लोकलहोस्ट ठीक है। धन्यवाद
एडम प्लोचर

20

सिंटैक्स मेरे लिए गलत था, आपको उद्धरण शामिल करना चाहिए:

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

अन्यथा मुझे "पैरामीटर गलत है" प्राप्त हुआ


4
"पैरामीटर गलत है" भी लौटाया जा सकता है यदि आप /url पर अनुगामी निर्दिष्ट नहीं करते हैं
LostSalad

13

यदि आप ध्वज "उपयोगकर्ता = हर कोई" का उपयोग करना चाहते हैं, तो आपको इसे अपनी सिस्टम भाषा में समायोजित करने की आवश्यकता है। अंग्रेजी में इसका उल्लेख है:

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

जर्मन में यह होगा:

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

1
स्पेनिश-भाषा प्रणालियों में, ऐसा करें: उपयोगकर्ता = टोडोस
रोड्रिगो रोड्रिग्स

इसके अलावा, मुझे URL को उद्धरण में रखने की आवश्यकता है, जैसा कि एक अन्य उत्तर में बताया गया है।
कार्स्टन फुरमैन

10

एक विकल्प के रूप में आपको उत्थान या जाल की आवश्यकता नहीं होती है आप उदाहरण के लिए 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);
        }
    });
}

यह वास्तव में उपयोगी था क्योंकि हमारे पास पहचान पत्र के लिए एक IBrowser लागू करते समय HttpListener मुद्दा था। उपरोक्त पुस्तकालय के लिए बहुत समान उपयोग मामला।
मैके

1
यह ध्यान देने योग्य है कि ऊपर दिए गए कोड में हालांकि बग हैं। सबसे पहले UTF8 के साथ एक स्ट्रीमवॉटर का उपयोग करने से कुछ ब्राउज़रों में समस्या होती है, मैं अनुमान लगा रहा हूं कि बीओएम आउटपुट या ऐसा कुछ होने के कारण। मैंने इसे बदलकर ASCII कर दिया और सब ठीक हो गया। मैंने धारा में पढ़ने के लिए डेटा उपलब्ध होने की प्रतीक्षा करने के लिए कुछ कोड भी जोड़े क्योंकि यह कभी-कभी कोई डेटा नहीं लौटाता।
मैके

धन्यवाद @mackie - यह हिस्सा वास्तव में Microsoft के स्वयं के नमूने से लिया गया था। मुझे लगता है कि वे वास्तव में ठीक से परीक्षण नहीं किया था। यदि आप मेरे उत्तर को संपादित कर आगे बढ़ सकते हैं और तरीकों को ठीक कर सकते हैं - अन्यथा शायद मुझे बदलाव भेजें और मैं इसे अपडेट कर सकता हूं।
माइकल ऑलसेन

2
एएससीआईआई का उपयोग करने के बजाय किसी को निम्नलिखित निर्माणकर्ता का उपयोग करना चाहिए new UTF8Encoding(false), जो कि बीओएम के उत्सर्जन को अक्षम करता है। मैंने इसे पहले ही उत्तर में बदल दिया है
सेबस्टियन

मैं स्वीकृत उत्तर पर इस समाधान को पसंद करता हूं। रनिंग नेट्स एक हैक की तरह लगता है। यह एक ठोस प्रोग्रामेटिक समाधान है। धन्यवाद!
जिम गोम्स

7

यदि आप अपने प्रोजेक्ट में एप्लिकेशन मेनिफेस्ट जोड़ते हैं तो आप अपने एप्लिकेशन को व्यवस्थापक के रूप में शुरू कर सकते हैं।

बस अपने प्रोजेक्ट में नया आइटम जोड़ें और "एप्लिकेशन मेनिफेस्ट फाइल" चुनें। <requestedExecutionLevel>तत्व को इसमें बदलें :

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

7

डिफ़ॉल्ट रूप से विंडोज निम्नलिखित उपसर्ग को परिभाषित करता है जो सभी के लिए उपलब्ध है: http: // +: 80 / Temporary_Listen_AAresses /

इसलिए आप अपना पंजीकरण करा सकते हैं HttpListener:

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

यह कभी-कभी सॉफ़्टवेयर जैसे Skype के साथ समस्या का कारण बनता है जो डिफ़ॉल्ट रूप से पोर्ट 80 का उपयोग करने का प्रयास करेगा।


1
स्काइप अपराधी था। मैंने पोर्ट बदलकर 80 नहीं किया और यह काम कर गया।
गोटो

5
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


यह मेरे लिए था। यह मेरे लिए काम किया.Add("http://+:9000/")
जॉन Gietzen

2

मुझे भी इसी तरह की समस्या का सामना करना पड़ा है। यदि आप पहले ही url आरक्षित कर चुके हैं तो आपको पहले url को नॉन एडमिन मोड में चलाने के लिए डिलीट करना होगा अन्यथा यह Access के साथ विफल हो जाएगा।

netsh http delete urlacl url=http://+:80
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.