1

この投稿に関して、C#クライアントからのApache NTLM Authは、自己定義の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); 
    }
  }
}

サーバー(Ruby on Rails over Apache / Thin)を使用するCredentialCache.DefaultNetworkCredentialsと、ユーザー名とリモートアドレスを取得できます。

コード(ルビーコードサーバー側の一部):

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からusernameとclient_ipを取得しません。

では、何が間違っているのでしょうか、それとも何が恋しいのでしょうか。

アップデート:

セッションとヘッダーを検査するために、いくつかのrubyデバッグコードを挿入しました。実際、ユーザーとクライアントのIPはブラウザとhttpwebrequestで送信されます。ただし、何らかの理由でsession_record.update_attributes値を更新/保存しないでください。

だからそれは私が調査しなければならないルビーの問題です...c#のことはありません...

これは、client_ipとusernameが正常に更新されたブラウザーのヘッダーのRoR検査です。

{"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]}

そして、ここでは、client_ipとusernameも持っているが、データベースが更新されないWebリクエストから:

{"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}
4

1 に答える 1

0

さて、さらにテストした後、私は最終的に問題を見つけました:私protect_from_forgeryたちはアプリケーションコントローラーで使用します。

だから、それはskip_before_filter :verify_authenticity_token私のlognコントローラーに設定するのに役立ちました。

しかし、これは私には回避策のように見え、私はそれについて気分が良くありません。

私はRailsのプロではありませんが、最初のリクエストでトークンを送信する必要があるのはなぜですか。トークンは、から直接ログインコントローラーに送信されますhttpwebrequest

編集1:

誰かがこれを正しく管理する方法の手がかり、説明、またはリンクを持っていますか?言い換えれば、私のログインコントローラーは認証のみを行うので、セキュリティの観点から、このコントローラーで認証トークンを無効にしても問題ありませんか?

編集2:

私はこれを見つけました:RailsAuthenticityTokenを理解する。ただし、トークンを取得してC#クライアントに保存し、リクエストごとに再送信する方法を知る必要があります。またはまったく必要ありませんか?

于 2012-11-03T10:13:04.207 に答える