2012-06-02 24 views
11

मैं अपने asmx वेब सेवा में उपयोगकर्ता नाम और पासवर्ड सत्यापन का उपयोग करके मूल प्रमाणीकरण लागू करना चाहता हूं।
मैं डब्ल्यूसीएफ का उपयोग नहीं करना चाहता हूं और मुझे पता है कि यह सुरक्षित तरीका नहीं है, लेकिन मुझे https का उपयोग किए बिना मूल प्रमाणीकरण का उपयोग करने की आवश्यकता है।Asmx वेब सेवा मूल प्रमाणीकरण

मेरे वेब सेवा इस तरह है:

[WebService(Namespace = "http://www.mywebsite.com/")] 
public class Service1 
{ 
    [WebMethod] 
    public string HelloWorld() 
    { 
     return "Hello world"; 
    } 
} 

और मैं इस कस्टम HttpModule का उपयोग करें:

public class BasicAuthHttpModule : IHttpModule 
{ 
    void IHttpModule.Init(HttpApplication context) 
    { 
     context.AuthenticateRequest += new EventHandler(OnAuthenticateRequest); 
    } 

    void OnAuthenticateRequest(object sender, EventArgs e) 
    { 
     string header = HttpContext.Current.Request.Headers["Authorization"]; 

     if (header != null && header.StartsWith("Basic")) //if has header 
     { 
      string encodedUserPass = header.Substring(6).Trim(); //remove the "Basic" 
      Encoding encoding = Encoding.GetEncoding("iso-8859-1"); 
      string userPass = encoding.GetString(Convert.FromBase64String(encodedUserPass)); 
      string[] credentials = userPass.Split(':'); 
      string username = credentials[0]; 
      string password = credentials[1]; 

      if(!MyUserValidator.Validate(username, password)) 
      { 
       HttpContext.Current.Response.StatusCode = 401; 
       HttpContext.Current.Response.End(); 
      } 
     } 
     else 
     { 
      //send request header for the 1st round 
      HttpContext context = HttpContext.Current; 
      context.Response.StatusCode = 401; 
      context.Response.AddHeader("WWW-Authenticate", String.Format("Basic realm=\"{0}\"", string.Empty)); 
     } 
    } 

    void IHttpModule.Dispose() 
    { 
    } 
} 

और web.config में मैं इस का उपयोग करें:

<?xml version="1.0"?> 
<configuration> 
    <appSettings/> 
    <connectionStrings/> 
    <system.web> 
     <customErrors mode="Off" /> 
     <compilation debug="true" targetFramework="4.0"/> 
     <authentication mode="None"/> 
    </system.web> 
    <system.webServer> 
     <modules runAllManagedModulesForAllRequests="true"> 
      <add name="BasicAuthHttpModule" 
       type="AuthService.BasicAuthHttpModule, AuthService" /> 
     </modules> 
    </system.webServer> 
</configuration>  

कॉलिंग कोड है:

static void Main(string[] args) 
{ 
    var proxy = new Service1.Service1() 
        { 
         Credentials = new NetworkCredential("user1", "[email protected]"), 
         PreAuthenticate = true 
        }; 
    try 
    { 
     var result = proxy.HelloWorld(); 
     Console.WriteLine(result); 
    } 
    catch (Exception e) 
    { 
     Console.WriteLine(e.Message); 
    } 
    Console.ReadKey(); 
} 

जब मैं इस वेब सेवा का उपयोग करता हूं, तो सेवा बुनियादी प्रमाणीकरण के लिए पूछती है लेकिन OnAuthenticateRequest विधि में परिवर्तनीय हमेशा शून्य है और MyUserValidator.Validate() कभी नहीं चलता है।

संपादित

Fiddler परिणाम:

POST http://www.mywebsite.com/Service1.asmx HTTP/1.1 
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 2.0.50727.4927) 
VsDebuggerCausalityData: uIDPo+drc57U77xGu/ZaOdYvw6IAAAAA8AjKQNpkV06FEWDEs2Oja2C+h3kM7dlDvnFfE1VlIIIACQAA 
Content-Type: text/xml; charset=utf-8 
SOAPAction: "http://www.mywebsite.com/HelloWorld" 
Host: www.mywebsite.com 
Content-Length: 291 
Expect: 100-continue 
Connection: Keep-Alive 

<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><HelloWorld xmlns="http://www.mywebsite.com/" /></soap:Body></soap:Envelope> 
HTTP/1.1 401 Unauthorized 
Cache-Control: private 
Content-Type: text/html 
Server: Microsoft-IIS/7.5 
WWW-Authenticate: Basic realm="" 
X-AspNet-Version: 4.0.30319 
WWW-Authenticate: Basic realm="www.mywebsite.com" 
X-Powered-By: ASP.NET 
Date: Sun, 03 Jun 2012 07:14:40 GMT 
Content-Length: 1293 
------------------------------------------------------------------ 

POST http://www.mywebsite.com/Service1.asmx HTTP/1.1 
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 2.0.50727.4927) 
VsDebuggerCausalityData: uIDPo+drc57U77xGu/ZaOdYvw6IAAAAA8AjKQNpkV06FEWDEs2Oja2C+h3kM7dlDvnFfE1VlIIIACQAA 
Content-Type: text/xml; charset=utf-8 
SOAPAction: "http://www.mywebsite.com/HelloWorld" 
Authorization: Basic dXNlcjE6cEBzc3cwcmQ= 
Host: www.mywebsite.com 
Content-Length: 291 
Expect: 100-continue 

<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><HelloWorld xmlns="http://www.mywebsite.com/" /></soap:Body></soap:Envelope> 
HTTP/1.1 401 Unauthorized 
Content-Type: text/html 
Server: Microsoft-IIS/7.5 
WWW-Authenticate: Basic realm="www.mywebsite.com" 
X-Powered-By: ASP.NET 
Date: Sun, 03 Jun 2012 07:14:41 GMT 
Content-Length: 1293 
------------------------------------------------------------------ 
+0

क्या आप वाकई इसे कभी नहीं चलाते हैं? क्या आपने इसकी पुष्टि करने में ब्रेकपॉइंट लगाया है? –

+0

हाँ मुझे यकीन है। हमेशा 'else' ब्लॉक चलाता है –

+0

मैंने इसे प्रश्न में जोड़ा। –

उत्तर

10

बदलें अपनी कस्टम एचटीपीएमओ यह करने के लिए dule कोड:

public class BasicAuthHttpModule : IHttpModule 
{ 
    public void Dispose() 
    { 
    } 

    public void Init(HttpApplication application) 
    { 
     application.AuthenticateRequest += new 
      EventHandler(this.OnAuthenticateRequest); 
     application.EndRequest += new 
      EventHandler(this.OnEndRequest); 
    } 

    public void OnAuthenticateRequest(object source, EventArgs 
         eventArgs) 
    { 
     HttpApplication app = (HttpApplication)source; 

     string authHeader = app.Request.Headers["Authorization"]; 
     if (!string.IsNullOrEmpty(authHeader)) 
     { 
      string authStr = app.Request.Headers["Authorization"]; 

      if (authStr == null || authStr.Length == 0) 
      { 
       return; 
      } 

      authStr = authStr.Trim(); 
      if (authStr.IndexOf("Basic", 0) != 0) 
      { 
       return; 
      } 

      authStr = authStr.Trim(); 

      string encodedCredentials = authStr.Substring(6); 

      byte[] decodedBytes = 
      Convert.FromBase64String(encodedCredentials); 
      string s = new ASCIIEncoding().GetString(decodedBytes); 

      string[] userPass = s.Split(new char[] { ':' }); 
      string username = userPass[0]; 
      string password = userPass[1]; 

      if (!MyUserValidator.Validate(username, password)) 
      { 
       DenyAccess(app); 
       return; 
      } 
     } 
     else 
     { 
      app.Response.StatusCode = 401; 
      app.Response.End(); 
     } 
    } 
    public void OnEndRequest(object source, EventArgs eventArgs) 
    { 
     if (HttpContext.Current.Response.StatusCode == 401) 
     { 
      HttpContext context = HttpContext.Current; 
      context.Response.StatusCode = 401; 
      context.Response.AddHeader("WWW-Authenticate", "Basic Realm"); 
     } 
    } 

    private void DenyAccess(HttpApplication app) 
    { 
     app.Response.StatusCode = 401; 
     app.Response.StatusDescription = "Access Denied"; 
     app.Response.Write("401 Access Denied"); 
     app.CompleteRequest(); 
    } 
} 

फिर Anonymous authentication सक्षम और आईआईएस में अपनी वेबसाइट के लिए अक्षम करें Basic, Digest और Windows प्रमाणीकरण।

नोट: यह कार्यान्वयन डब्ल्यूसीएफ के साथ भी काम करेगा।

+0

मेरे मामले में मुझे भी अनाम प्रमाणीकरण को अक्षम करना पड़ा। ' <प्रमाणीकरण> । ..' – Evilripper

+0

मेरे लिए यह केवल एक एप्लिकेशन पूल में काम कर रहा है जो "एकीकृत अनुप्रयोग पूल मोड" का उपयोग करता है - क्लासिक मोड में काम नहीं कर रहा है। लेकिन मैं समझा नहीं सकता कि वास्तव में क्यों ... – Lopo

+0

मेरे लिए काम किया ... मुझे web.config अनुभाग को संपादित करना पड़ा। = "BasicAuthHttpModule" टाइप करने के लिए टाइप = "AuthService.BasicAuthHttpModule, AuthService" से प्रकार बदलें। मैंने यह सुनिश्चित किया है कि मैंने जो क्लास जोड़ा है BasicAuthHttpModule में नामस्थान नहीं है। –

1

ऐसा लगता है कि आप हेडर मैन्युअल भेज पहली बार की जरूरत है:

Rick Strahl's Blog से

string url = "http://rasnote/wconnect/admin/wc.wc?_maintain~ShowStatus"; 
    HttpWebRequest req = HttpWebRequest.Create(url) as HttpWebRequest; 

    string user = "ricks"; 
    string pwd = "secret"; 
    string domain = "www.west-wind.com"; 

    string auth = "Basic " + Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(user + ":" + pwd)); 
    req.PreAuthenticate = true; 
    req.Headers.Add("Authorization", auth); 
    req.UserAgent = ": Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 4.0.20506)"; 
    WebResponse resp = req.GetResponse(); 
    resp.Close(); 
+0

मैं इस कोड का उपयोग करता हूं और यह 'WebResponse resp = req.GetResponse(); –

+0

पर प्रमाणीकरण त्रुटि भी देता है क्या आपने पूर्व प्रमाणीकरण के बारे में शेष लेख का पालन किया था? –

संबंधित मुद्दे