httpwebrequest不发送带有自定义网络凭据的客户端头?

时间:2012-10-29 19:47:05

标签: ruby-on-rails session-variables

关于这篇文章Apache NTLM Auth from C# client do not work with self defined NetworkCredentials我添加了一种方法进行身份验证。 我以为我今天完成了我的工作:)但是我遇到了另一个问题。

代码:

public static void Authenticate()
{
  Stream requestStream = null;
  string loginUrl = Common.WindowAuthentication ? Common.PortalUrl + Common.IoiLoginWin : Common.PortalUrl + Common.IoiLogin;

  var request = (HttpWebRequest)WebRequest.Create(loginUrl);
  request.Method = WebRequestMethods.Http.Post;
  request.AllowAutoRedirect = true;
  request.CookieContainer = Common.Cookies;
  request.Accept = @"*/*";

  if (Common.WindowAuthentication)
  {
    if (Common.UserName.Length > 0)
    {
      string[] domainuser;
      string username;
      string domain;

      if (Common.UserName.Contains("@"))
      {
        domainuser = Common.UserName.Split('@');
        username = domainuser[0];
        domain = domainuser[1];
      }
      else
      {
        domainuser = Common.UserName.Split('\\');
        username = domainuser[1];
        domain = domainuser[0];
      }
      var nc = new NetworkCredential(username, Common.Password, domain);
      var cache = new CredentialCache();
      cache.Add(request.RequestUri, "NTLM", nc);
      request.Credentials = cache;
    }
    else
    {
      request.Credentials = CredentialCache.DefaultNetworkCredentials;
    }
  }
  else
  {
    string payload = Common.ParmLogin + Common.UserName + "&" + Common.ParmPass + Common.Password;
    StringBuilder urlEncoded = new StringBuilder();
    Char[] reserved = { '?', '=', '&' };
    byte[] byteBuffer;

    if (payload != null)
    {
      int i = 0, j;
      while (i < payload.Length)
      {
        j = payload.IndexOfAny(reserved, i);
        if (j == -1)
        {
          urlEncoded.Append(HttpUtility.UrlEncode(payload.Substring(i, payload.Length - i)));
          break;
        }
        urlEncoded.Append(HttpUtility.UrlEncode(payload.Substring(i, j - i)));
        urlEncoded.Append(payload.Substring(j, 1));
        i = j + 1;
      }
      byteBuffer = Encoding.UTF8.GetBytes(urlEncoded.ToString());
      request.ContentLength = byteBuffer.Length;
      requestStream = request.GetRequestStream();
      requestStream.Write(byteBuffer, 0, byteBuffer.Length);
      requestStream.Close();
    }
    else
    {
      request.ContentLength = 0;
    }
    if (Common.LogCommunicatin)
      LogCommunication(loginUrl, payload);
  }

  using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
  {
    if (response.StatusCode.ToString() == "OK") {
      WebHeaderCollection c = response.Headers;
      Common.SessionCookie = Common.Cookies.GetCookies(new Uri(loginUrl))["_ror_session"].Value;
      if (Common.LogCommunicatin)
        LogCommunication(loginUrl, "Cookie: " + Common.SessionCookie); 
    }
  }
}

当我使用CredentialCache.DefaultNetworkCredentials时,服务器(基于Apache / Thin的Ruby on Rails)能够获取用户名和远程地址。

代码(ruby代码服务器端的一部分):

begin
  cookies[:user] = { :value => user.strusername, :expires => 1.month.from_now }
  session[:current_user_id] = user.id
  session_record = request.env['rack.session.record']
  session_record.update_attributes({
    :username => user.strusername,
    :client_ip => (request.env['HTTP_X_FORWARDED_FOR']||request.env['REMOTE_ADDR'])
  })
rescue => e
end

但是当我使用自己的凭据时,服务器不会从httpwebrequest获取用户名和client_ip。

那么我错了什么或者我错过了什么?

更新

我插入了一些ruby调试代码来检查会话和标头。 实际上,用户和客户端ip是在浏览器和httpwebrequest中发送的。 但由于任何原因,session_record.update_attributes不会更新/保存值。

所以这是一个我需要调查的红宝石问题......没有c#thingy ......

以下是对浏览器标题的RoR检查,其中client_ip和用户名已成功更新:

{"SERVER_SOFTWARE"=>"thin 1.2.11 codename Bat-Shit Crazy", "SERVER_NAME"=>"thorx64", "rack.input"=>#<StringIO:0x9f4db08>, "rack.version"=>[1, 0], "rack.errors"=>#<IO:<STDERR>>, "rack.multithread"=>false, "rack.multiprocess"=>false, "rack.run_once"=>false, "REQUEST_METHOD"=>"GET", "REQUEST_PATH"=>"/ror/login.json", "PATH_INFO"=>"/login.json", "REQUEST_URI"=>"/ror/login.json", "HTTP_VERSION"=>"HTTP/1.1", "HTTP_HOST"=>"thorx64", "HTTP_ACCEPT"=>"image/jpeg, image/gif, image/pjpeg, application/x-ms-application, application/xaml+xml, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*", "HTTP_ACCEPT_LANGUAGE"=>"de-DE", "HTTP_USER_AGENT"=>"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET4.0C; .NET4.0E; .NET CLR 3.5.30729; .NET CLR 3.0.30729)", "HTTP_ACCEPT_ENCODING"=>"gzip, deflate", "HTTP_AUTHORIZATION"=>"NTLM TlRMTVNTUAADAAAAAAAAAFgAAAAAAAAAWAAAAAAAAABYAAAAAAAAAFgAAAAAAAAAWAAAAAAAAABYAAAABcKIogYBsR0AAAAPB3e6Q1YIzZ10PiKm2g/S6A==", "HTTP_COOKIE"=>"user=Administrator", "HTTP_X_ISRW_PROXY_AUTH_USER"=>"Administrator", "HTTP_MAX_FORWARDS"=>"10", "HTTP_X_FORWARDED_FOR"=>"192.168.14.21", "HTTP_X_FORWARDED_HOST"=>"thorx64", "HTTP_X_FORWARDED_SERVER"=>"thorx64", "HTTP_CONNECTION"=>"Keep-Alive", "GATEWAY_INTERFACE"=>"CGI/1.2", "SERVER_PORT"=>"80", "QUERY_STRING"=>"", "SERVER_PROTOCOL"=>"HTTP/1.1", "rack.url_scheme"=>"http", "SCRIPT_NAME"=>"/ror", "REMOTE_ADDR"=>"127.0.0.1", "async.callback"=>#<Method: Thin::Connection#post_process>, "async.close"=>#<EventMachine::DefaultDeferrable:0x9f4c4d0>, "action_dispatch.parameter_filter"=>[:password], "action_dispatch.secret_token"=>"a1ef5e037607d12742a40a0793de973a5e68605ccf087ad1baedaee6d811687b82a0671b94da2c4a9af2b481a5346585649e83d2f56f2838a4aca8eedbfc93b7", "action_dispatch.show_exceptions"=>true, "action_dispatch.remote_ip"=>127.0.0.1, "rack.session"=>{}, "rack.session.options"=>{:path=>"/", :domain=>nil, :expire_after=>nil, :secure=>false, :httponly=>true, :id=>nil}, "rack.request.cookie_string"=>"user=Administrator", "rack.request.cookie_hash"=>{"user"=>"Administrator"}, "action_dispatch.request.path_parameters"=>{:controller=>"login", :action=>"index", :format=>"json"}, "action_controller.instance"=>#<LoginController:0xb6d59a0 @action_has_layout=true, @view_context_class=nil, @_headers={"Content-Type"=>"text/html"}, @_status=200, @_response=#<ActionDispatch::Response:0xb6d5760 @writer=#<Proc:0xb6d54f0@D:/Informer/ruby/lib/ruby/gems/1.9.1/gems/actionpack-3.0.10/lib/action_dispatch/http/response.rb:43 (lambda)>, @block=nil, @length=0, @header={}, @status=200, @body=[], @cookie=[], @sending_file=false, @blank=false, @cache_control={}, @etag=nil, @request=#<ActionDispatch::Request:0xb6d5778 @env={...}, @request_method="GET", @filtered_parameters={"controller"=>"login", "action"=>"index", "format"=>"json"}, @method="GET", @fullpath="/ror/login.json">>, @_request=#<ActionDispatch::Request:0xb6d5778 @env={...}, @request_method="GET", @filtered_parameters={"controller"=>"login", "action"=>"index", "format"=>"json"}, @method="GET", @fullpath="/ror/login.json">, @_env={...}, @lookup_context=#<ActionView::LookupContext:0xb6c3d60 @details_key=nil, @details={:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html, :text, :js, :css, :ics, :csv, :xml, :rss, :atom, :yaml, :multipart_form, :url_encoded_form, :json, :flv, :file, :image, :auto, :sourcefile, :sourceimage, :sourceauto, :legacy, :edit], :locale=>[:de, :de]}, @skip_default_locale=false, @frozen_formats=false, @view_paths=[d:/Informer/company/latest/ror/app/views, d:/Informer/company/latest/ror/vendor/plugins/will_paginate/app/views, d:/Informer/company/latest/ror/vendor/plugins/usesguid/app/views, d:/Informer/company/latest/ror/vendor/plugins/acts_as_tree/app/views]>, @_action_name="index", @_response_body=nil, @_config={}, @_params={"controller"=>"login", "action"=>"index", "format"=>"json"}, @_current_user=nil>, "action_dispatch.request.content_type"=>nil, "action_dispatch.request.request_parameters"=>{}, "rack.request.query_string"=>"", "rack.request.query_hash"=>{}, "action_dispatch.request.query_parameters"=>{}, "action_dispatch.request.parameters"=>{"controller"=>"login", "action"=>"index", "format"=>"json"}, "action_dispatch.request.formats"=>[application/json]}

这里来自web请求,我有client_ip和用户名,但数据库没有更新:

{"SERVER_SOFTWARE"=>"thin 1.2.11 codename Bat-Shit Crazy", "SERVER_NAME"=>"thorx64", "rack.input"=>#<StringIO:0xa3a3778>, "rack.version"=>[1, 0], "rack.errors"=>#<IO:<STDERR>>, "rack.multithread"=>false, "rack.multiprocess"=>false, "rack.run_once"=>false, "REQUEST_METHOD"=>"POST", "REQUEST_PATH"=>"/ror/login.json", "PATH_INFO"=>"/login.json", "REQUEST_URI"=>"/ror/login.json", "HTTP_VERSION"=>"HTTP/1.1", "HTTP_HOST"=>"thorx64", "HTTP_ACCEPT"=>"*/*", "HTTP_X_REQUESTED_WITH"=>"XMLHttpRequest", "HTTP_USER_AGENT"=>"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET4.0C; .NET4.0E; .NET CLR 3.5.30729; .NET CLR 3.0.30729)", "HTTP_AUTHORIZATION"=>"NTLM TlRMTVNTUAADAAAAGAAYAH4AAACgAaABlgAAAAwADABYAAAADAAMAGQAAAAOAA4AcAAAAAAAAAA2AgAABYKIogYBsR0AAAAPGyWqqmBHFtGQTE/QMlHT7XQAcQBzAG8AZgB0AHIAYQB1AHMAYwBoAFQASABPAFIAWAA2ADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoZP5isSr442bUTMoUknN3QEBAAAAAAAAZCgelIW2zQH2AaAgXe6DYQAAAAACAAwAVABRAFMATwBGAFQAAQAOAFQASABPAFIAWAA2ADQABAAsAGYAcgBhAC4AZwBlAHIAbQBhAG4AeQAuAHQAcQBzAG8AZgB0AC4AbgBlAHQAAwA8AFQASABPAFIAeAA2ADQALgBmAHIAYQAuAGcAZQByAG0AYQBuAHkALgB0AHEAcwBvAGYAdAAuAG4AZQB0AAUALABmAHIAYQAuAGcAZQByAG0AYQBuAHkALgB0AHEAcwBvAGYAdAAuAG4AZQB0AAcACABkKB6UhbbNAQYABAACAAAACAAwADAAAAAAAAAAAAAAAAAwAAAgXEA1/+dnAlRife8JhCuzKyRGkcsJKXvyXzrION0KdwoAEAAAAAAAAAAAAAAAAAAAAAAACQBGAEgAVABUAFAALwBUAEgATwBSAHgANgA0AC4AZgByAGEALgBnAGUAcgBtAGEAbgB5AC4AdABxAHMAbwBmAHQALgBuAGUAdAAAAAAAAAAAAAAAAAA=", "HTTP_X_ISRW_PROXY_AUTH_USER"=>"rausch", "HTTP_MAX_FORWARDS"=>"10", "HTTP_X_FORWARDED_FOR"=>"192.168.14.21", "HTTP_X_FORWARDED_HOST"=>"thorx64", "HTTP_X_FORWARDED_SERVER"=>"thorx64", "HTTP_CONNECTION"=>"Keep-Alive", "GATEWAY_INTERFACE"=>"CGI/1.2", "SERVER_PORT"=>"80", "QUERY_STRING"=>"", "SERVER_PROTOCOL"=>"HTTP/1.1", "rack.url_scheme"=>"http", "SCRIPT_NAME"=>"/ror", "REMOTE_ADDR"=>"127.0.0.1", "async.callback"=>#<Method: Thin::Connection#post_process>, "async.close"=>#<EventMachine::DefaultDeferrable:0xa3a28f0>, "action_dispatch.parameter_filter"=>[:password], "action_dispatch.secret_token"=>"a1ef5e037607d12742a40a0793de973a5e68605ccf087ad1baedaee6d811687b82a0671b94da2c4a9af2b481a5346585649e83d2f56f2838a4aca8eedbfc93b7", "action_dispatch.show_exceptions"=>true, "action_dispatch.remote_ip"=>127.0.0.1, "rack.session"=>{}, "rack.session.options"=>{:path=>"/", :domain=>nil, :expire_after=>nil, :secure=>false, :httponly=>true, :id=>nil}, "rack.request.form_input"=>#<StringIO:0xa3a3778>, "rack.request.form_hash"=>{}, "rack.request.form_vars"=>"", "action_dispatch.request.path_parameters"=>{:controller=>"login", :action=>"index", :format=>"json"}, "action_controller.instance"=>#<LoginController:0xb9d86a0 @action_has_layout=true, @view_context_class=nil, @_headers={"Content-Type"=>"text/html"}, @_status=200, @_response=#<ActionDispatch::Response:0xb9d8460 @writer=#<Proc:0xb9d8388@D:/Informer/ruby/lib/ruby/gems/1.9.1/gems/actionpack-3.0.10/lib/action_dispatch/http/response.rb:43 (lambda)>, @block=nil, @length=0, @header={}, @status=200, @body=[], @cookie=[], @sending_file=false, @blank=false, @cache_control={}, @etag=nil, @request=#<ActionDispatch::Request:0xb9d8478 @env={...}, @request_method="POST", @filtered_parameters={"controller"=>"login", "action"=>"index", "format"=>"json"}, @method="POST", @fullpath="/ror/login.json">>, @_request=#<ActionDispatch::Request:0xb9d8478 @env={...}, @request_method="POST", @filtered_parameters={"controller"=>"login", "action"=>"index", "format"=>"json"}, @method="POST", @fullpath="/ror/login.json">, @_env={...}, @lookup_context=#<ActionView::LookupContext:0xb9d55f8 @details_key=nil, @details={:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html, :text, :js, :css, :ics, :csv, :xml, :rss, :atom, :yaml, :multipart_form, :url_encoded_form, :json, :flv, :file, :image, :auto, :sourcefile, :sourceimage, :sourceauto, :legacy, :edit], :locale=>[:de, :de]}, @skip_default_locale=false, @frozen_formats=false, @view_paths=[d:/Informer/company/latest/ror/app/views, d:/Informer/company/latest/ror/vendor/plugins/will_paginate/app/views, d:/Informer/company/latest/ror/vendor/plugins/usesguid/app/views, d:/Informer/company/latest/ror/vendor/plugins/acts_as_tree/app/views]>, @_action_name="index", @_response_body=nil, @_config={}, @_params={"controller"=>"login", "action"=>"index", "format"=>"json"}, @_current_user=nil>, "action_dispatch.request.request_parameters"=>{}, "rack.request.query_string"=>"", "rack.request.query_hash"=>{}, "action_dispatch.request.query_parameters"=>{}, "action_dispatch.request.parameters"=>{"controller"=>"login", "action"=>"index", "format"=>"json"}, "action_dispatch.request.formats"=>[application/json], "rack.session.record"=>#<ActiveRecord::SessionStore::Session id: nil, session_id: "14e03319c61b707318dd50066340be95", client_ip: nil, username: nil, data: nil, created_at: nil, updated_at: nil>, "action_dispatch.request.flash_hash"=>nil}

1 个答案:

答案 0 :(得分:0)

确定, 经过更多的测试后我终于找到了问题: 我们在应用程序控制器中使用protect_from_forgery

所以它有助于在我的logn控制器中设置skip_before_filter :verify_authenticity_token

但这对我来说似乎是一种解决方法,而且我对它没有很好的感觉。

我不是专业人士,但我想知道为什么我必须在我的第一个请求中发送一个令牌,该请求直接从我的httpwebrequest发送到登录控制器。

编辑1:

任何人都有线索,解释或链接如何管理这个正确吗? 或者换句话说:由于我的登录控制器只能进行身份验证,从安全角度来看,可以在此控制器上禁用身份验证令牌吗?

编辑2:

我发现了这个:Understanding the Rails Authenticity Token。 但是现在我需要知道如何获取令牌并将其存储在我的C#客户端中以便在每次请求时重新发送它。或者根本不需要?