2010-07-15 60 views
12

IBM的RTC REST的API给shell脚本的例子与服务器进行身份验证:C# - WebRequest的HTTP POST与曲奇(端口从卷曲脚本)

COOKIES=./cookies.txt 

USER=my_user 
PASSWORD=my_password 
HOST="https://myJazzServer:9092/jazz" 

curl -k -c $COOKIES "$HOST/authenticated/identity" 

curl -k -L -b $COOKIES -c $COOKIES -d j_username=$USER -d j_password=$PASSWORD "$HOST/authenticated/j_security_check" 

这完美的作品,但我需要验证与服务器使用C#。

到目前为止,我有以下的,但它不工作(返回授权失败页):

CookieContainer _cookie; 

    public string _RTC() 
    { 
     HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://myJazzServer.com:9092/jazz/authenticated/identity"); 
     if (_cookie == null) 
     { 
      _cookie = new CookieContainer(); 
     } 
     string a; 
     request.CookieContainer = _cookie; 
     using (var response = request.GetResponse()) 
     { 
      using (StreamReader sr = new StreamReader(response.GetResponseStream())) 
      { 
       a = sr.ReadToEnd(); 
      } 
     } 




     byte[] data = (new ASCIIEncoding()).GetBytes("j_username=myUser&j_password=MyPass"); 

     request = (HttpWebRequest)WebRequest.Create("https://myJazzServer.com:9092/jazz/authenticated/j_security_check"); 

     request.Method = "POST"; 
     request.ContentType = "text/html"; 
     request.ContentLength = data.Length; 
     request.CookieContainer = _cookie; 
     Stream reqStream = request.GetRequestStream(); 
     reqStream.Write(data,0,data.Length); 

     string b; 

     using (var response = request.GetResponse()) 
     { 
      using (var reader = new StreamReader(response.GetResponseStream())) 
      { 
       b = reader.ReadToEnd(); 
      } 
     } 
    } 
+0

你能更具体一点关于什么是“不工作”?您是否收到异常,响应中没有内容,响应中有意外的http状态代码(例如404,407等)? – Nathan 2010-07-17 17:17:50

+0

@Nathan,它返回一个授权失败的页面,我不能给出详细信息,因为它返回的是一个名为authFailed(或类似的东西)的方法的ajax引导程序,所以我无法得到实际的细节。 – 2010-07-17 17:26:09

回答

20

我建议你尝试以下方法:

public class WebClientEx : WebClient 
{ 
    private CookieContainer _cookieContainer = new CookieContainer(); 

    protected override WebRequest GetWebRequest(Uri address) 
    { 
     WebRequest request = base.GetWebRequest(address); 
     if (request is HttpWebRequest) 
     { 
      (request as HttpWebRequest).CookieContainer = _cookieContainer; 
     } 
     return request; 
    } 
} 

class Program 
{ 
    static void Main() 
    { 
     using (var client = new WebClientEx()) 
     { 
      var response1 = client.DownloadString("https://myJazzServer.com:9092/jazz/authenticated/identity"); 

      var data = new NameValueCollection 
      { 
       { "j_username", "myUser" }, 
       { "j_password", "MyPass" }, 
      }; 
      var response2 = client.UploadValues("https://myJazzServer.com:9092/jazz/authenticated/j_security_check", data); 
      Console.WriteLine(Encoding.Default.GetString(response2)); 
     } 
    } 
} 

而且简化调试你可以通过把它放在你的app.config中激活跟踪:

<configuration> 

    <system.diagnostics> 
    <sources> 
     <source name="System.Net.Sockets" tracemode="protocolonly"> 
     <listeners> 
      <add name="System.Net.Sockets" type="System.Diagnostics.TextWriterTraceListener" initializeData="network.log" /> 
     </listeners> 
     </source> 
    </sources> 

    <switches> 
     <add name="System.Net.Sockets" value="Verbose"/> 
    </switches> 

    <trace autoflush="true" /> 
    </system.diagnostics> 
</configuration> 

这将创建网络活动的详细日志文件,可能会简化调试。

+0

那么第一次工作,除了你的产品比我的产品好1000倍之外,我不确定它为什么有效,我的产品没有,但它现在正在工作,那就是重要的。赏金公司22小时:) 非常感谢! – 2010-07-17 18:07:25

+0

如果存在“Set-Cookie”响应,您的实现将错过它,这可能导致身份验证失败。 – PerlDev 2010-08-13 18:59:24

+0

我把这段代码放到了一个我一直在从一个需要认证的网站获取资源的小应用中。我必须改变的是POST中发送的数据,它只是起作用。惊奇!现在我需要去弄清楚它是如何工作的,因为它看起来很神奇! – 2012-05-10 13:05:31

2

这里是另一种方法,如果你想使用HttpWebResponse/HttpWebRequest

public static HttpWebResponse requestSecureDocument(HttpWebRequest _request, string _rtcServerURL, string _userName, string _password) 
{ 
    //FormBasedAuth Step1: Request the resource and clone the request to be used later 
    HttpWebRequest _requestClone = WebRequestExtensions.CloneRequest(_request, _request.RequestUri); 
    //(HttpWebRequest)WebRequest.Create(request.RequestUri); 

    //store the response in _docResponse variable 
    HttpWebResponse _docResponse = (HttpWebResponse)_request.GetResponse(); 

    //HttpStatusCode.OK indicates that the request succeeded and that the requested information is in the response. 
    if (_docResponse.StatusCode == HttpStatusCode.OK) 
    { 
     //X-com-ibm-team-repository-web-auth-msg header signifies form based authentication is being used 
     string _rtcAuthHeader = _docResponse.Headers["X-com-ibm-team-repository-web-auth-msg"]; 
     if (_rtcAuthHeader != null && _rtcAuthHeader.Equals("authrequired")) 
     { 
      _docResponse.GetResponseStream().Flush(); 
      _docResponse.Close(); 

      //Prepare form for authentication as _rtcAuthHeader = authrequired 
      HttpWebRequest _formPost = (HttpWebRequest)WebRequest.Create(_rtcServerURL + "/j_security_check"); 
      _formPost.Method = "POST"; 
      _formPost.Timeout = 30000; 
      _formPost.CookieContainer = _request.CookieContainer; 
      _formPost.Accept = "text/xml"; 
      _formPost.ContentType = "application/x-www-form-urlencoded"; 

      String _authString = "j_username=" + _userName + "&amp;j_password=" + _password; 
      //create authentication string 
      Byte[] _outBuffer = Encoding.UTF8.GetBytes(_authString); //store in byte buffer 
      _formPost.ContentLength = _outBuffer.Length; 
      Stream _str = _formPost.GetRequestStream(); 
      _str.Write(_outBuffer, 0, _outBuffer.Length); //update form 
      _str.Close(); 

      //FormBasedAuth Step2:submit the login form and get the response from the server 
      HttpWebResponse _formResponse = (HttpWebResponse)_formPost.GetResponse(); 

      _rtcAuthHeader = _formResponse.Headers["X-com-ibm-team-repository-web-auth-msg"]; 
      //check if authentication has failed 
      if (_rtcAuthHeader != null && _rtcAuthHeader.Equals("authfailed")) 
      { 
       //authentication failed. You can write code to handle the authentication failure. 
       //if (DEBUG) Console.WriteLine("Authentication Failure"); 
      } 
      else 
      { 
       //login successful 
       _formResponse.GetResponseStream().Flush(); 
       _formResponse.Close(); 
       //FormBasedAuth Step3: Resend the request for the protected resource. 
       //if (DEBUG) Console.WriteLine("&gt;&gt; Response " + request.RequestUri); 
       return (HttpWebResponse)_requestClone.GetResponse(); 
      } 
     } 
    } 
    //already authenticated return original response_docResponse 
    return _docResponse; 
} 

你可以调用这个函数在你的代码 -

string _serverURL = https://localhost:9443/ccm; 
string _resourceURL = "https://localhost:9443/ccm/rootservices"; 

string mediatype = "application/xml"; 
string username = "username";          
string password = "password"; 
try 
{ 
    CookieContainer _cookies = new CookieContainer();//create cookie container 
    HttpWebRequest documentGet = (HttpWebRequest)WebRequest.Create(_resourceURL); 
    documentGet.Method = "GET"; //method 
    documentGet.CookieContainer = _cookies; //set container for HttpWebRequest 
    documentGet.Accept = mediatype; 
    documentGet.Headers.Set("OSLC-Core-Version", "3.0"); //for RTC 3.0.1.2 
    documentGet.Timeout = 300000; 
    HttpWebResponse response = requestSecureDocument(documentGet, _serverURL, username, password); 

    if (response.StatusCode != HttpStatusCode.OK) 
    { 
     Console.WriteLine(" Error: " + response.StatusDescription); 
     response.Close(); 
    } 
} 
catch (Exception ex) 
{ 
} 

你可以阅读更多at my blog