অনুরোধের সাথে শংসাপত্রগুলি পাস করার জন্য কীভাবে এইচটিটিপিপ্লায়েন্ট পাবেন?


164

আমার একটি ওয়েব অ্যাপ্লিকেশন রয়েছে (আইআইএস-এ হোস্ট করা) যা একটি উইন্ডোজ পরিষেবাতে কথা বলে। উইন্ডোজ পরিষেবাটি এএসপি.নেট এমভিসি ওয়েব এপিআই (স্ব-হোস্টেড) ব্যবহার করছে এবং তাই জেএসওএন ব্যবহার করে HTTP- র মাধ্যমে যোগাযোগ করা যেতে পারে। ওয়েব অ্যাপ্লিকেশনটি ছদ্মবেশ তৈরি করতে কনফিগার করা হয়েছে, এই ধারণাটি যে ব্যবহারকারী যে ওয়েব অ্যাপ্লিকেশনটিতে অনুরোধ করে তা ওয়েব অ্যাপ্লিকেশন পরিষেবাটিতে অনুরোধ করার জন্য ব্যবহার করা উচিত make কাঠামোটি এর মতো দেখাচ্ছে:

(লাল রঙে হাইলাইট করা ব্যবহারকারীটি নীচের উদাহরণগুলিতে ব্যবহারকারীকে উল্লেখ করা হচ্ছে))


ওয়েব অ্যাপ্লিকেশনটি একটি ব্যবহার করে উইন্ডোজ পরিষেবাতে অনুরোধ করে HttpClient:

var httpClient = new HttpClient(new HttpClientHandler() 
                      {
                          UseDefaultCredentials = true
                      });
httpClient.GetStringAsync("http://localhost/some/endpoint/");

এটি উইন্ডোজ পরিষেবাতে অনুরোধ করে, তবে শংসাপত্রগুলি সঠিকভাবে পাস করে না (পরিষেবাটি ব্যবহারকারী হিসাবে রিপোর্ট করে IIS APPPOOL\ASP.NET 4.0)। আমি যা হতে চাই তা এই নয়

আমি যদি WebClientপরিবর্তে ব্যবহারের জন্য উপরের কোডটি পরিবর্তন করি তবে ব্যবহারকারীর শংসাপত্রগুলি সঠিকভাবে পাস হয়ে গেছে:

WebClient c = new WebClient
                   {
                       UseDefaultCredentials = true
                   };
c.DownloadStringAsync(new Uri("http://localhost/some/endpoint/"));

উপরের কোড সহ, পরিষেবাটি ওয়েব অ্যাপ্লিকেশনটিতে অনুরোধটি করেছে এমন ব্যবহারকারী হিসাবে ব্যবহারকারীকে রিপোর্ট করে।

আমি HttpClientপ্রয়োগের ক্ষেত্রে কী ভুল করছি যা এর ফলে এটি শংসাপত্রগুলি সঠিকভাবে পাস করতে দেয় না (বা এটি দিয়ে কোনও বাগ রয়েছে HttpClient)?

যে কারণে আমি এটি ব্যবহার করতে চাই তা HttpClientহ'ল এতে একটি অ্যাসিঙ্ক এপিআই রয়েছে যা এসগুলির সাথে ভালভাবে কাজ করে Task, যেখানে WebClientএর এসাইক এপিআই ইভেন্টগুলির সাথে পরিচালনা করা দরকার।


সম্ভাব্য সদৃশ stackoverflow.com/q/10308938/1045728
টমি Grovnes

দেখে মনে হচ্ছে এইচটিপিপ্লেইয়েন্ট এবং ওয়েবক্লিয়েন্ট বিভিন্ন জিনিসকে ডিফল্ট শংসাপত্র হিসাবে বিবেচনা করে। আপনি কি HTTPClient.setCredentials (...) চেষ্টা করেছেন?
জার্মানি আর্লিংটন

বিটিডাব্লু, ওয়েবক্লিয়েন্টের DownloadStringTaskAsyncনেট নেট in.৫ রয়েছে , যা এসিএনসি / অপেক্ষার সাথেও ব্যবহার করা যেতে পারে
এলবি

1
@ জার্মানআরলিংটন: এর HttpClientকোনও SetCredentials()পদ্ধতি নেই। তুমি কি বলতে চাচ্ছো আমাকে?
এড্রিয়ানব্যাঙ্কস

4
এটি ঠিক হয়ে গেছে প্রদর্শিত হবে (.NET 4.5.1)? আমি new HttpClient(new HttpClientHandler() { AllowAutoRedirect = true, UseDefaultCredentials = true }একটি ওয়েব-সার্ভারে একটি উইন্ডোজ-অনুমোদিতীকৃত ব্যবহারকারী দ্বারা অ্যাক্সেস করা তৈরি করার চেষ্টা করেছি এবং ওয়েব সাইটটি এর পরে অন্য দূরবর্তী সংস্থার জন্য প্রমাণীকরণ করেছিল (পতাকা সেট ছাড়া প্রমাণীকরণ করবে না) would
GSerg

উত্তর:


67

আমারও একই সমস্যা ছিল নিম্নলিখিত এসও নিবন্ধে @ টিপিজিকের গবেষণার জন্য আমি একটি সিঙ্ক্রোনাস সলিউশন বিকাশ করেছি: এইচটিপিসিলেট সহ এএসপি.নেট ওয়েব এপি সার্ভিসে প্রমাণীকরণে অক্ষম

আমার সমাধানটি একটি ব্যবহার করে WebClient, যা আপনি সঠিকভাবে উল্লেখ করেছেন যে ইস্যু ছাড়াই শংসাপত্রগুলি পাস করে। কারণটি HttpClientকাজ করে না কারণ উইন্ডোজ সুরক্ষা একটি ছদ্মবেশী অ্যাকাউন্টের অধীনে নতুন থ্রেড তৈরি করার ক্ষমতা অক্ষম করায় (উপরে এসও নিবন্ধটি দেখুন see) HttpClientটাস্ক ফ্যাক্টরিটির মাধ্যমে নতুন থ্রেড তৈরি করে যাতে ত্রুটি ঘটে। WebClientঅন্যদিকে, একই থ্রেডের সাথে নিয়মটিকে বাইপাস করে এবং এর শংসাপত্রগুলি ফরোয়ার্ড করে সুসংগতভাবে চালিত হয়।

কোডটি কাজ করলেও, ক্ষতিটি হ'ল এটি async কাজ করবে না।

var wi = (System.Security.Principal.WindowsIdentity)HttpContext.Current.User.Identity;

var wic = wi.Impersonate();
try
{
    var data = JsonConvert.SerializeObject(new
    {
        Property1 = 1,
        Property2 = "blah"
    });

    using (var client = new WebClient { UseDefaultCredentials = true })
    {
        client.Headers.Add(HttpRequestHeader.ContentType, "application/json; charset=utf-8");
        client.UploadData("http://url/api/controller", "POST", Encoding.UTF8.GetBytes(data));
    }
}
catch (Exception exc)
{
    // handle exception
}
finally
{
    wic.Undo();
}

দ্রষ্টব্য: নিউগেট প্যাকেজটির দরকার: নিউটনসফট.জসন, যা একই জেএসএন সিরিয়ালাইজার ওয়েবএপিআই ব্যবহার করে।


1
আমি শেষের দিকে অনুরূপ কিছু করেছি, এবং এটি সত্যই ভাল কাজ করে। অ্যাসিঙ্ক্রোনাস ইস্যু কোনও সমস্যা নয়, কারণ আমি কলগুলি ব্লক করতে চাই।
adrianbanks

136

আপনি HttpClientস্বয়ংক্রিয়ভাবে শংসাপত্রগুলি পাস করার জন্য এটি কনফিগার করতে পারেন :

var myClient = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true });

11
আমি জানি যে কিভাবে করতে। আচরণটি আমি যা চাই তা নয় (প্রশ্নে বর্ণিত হিসাবে) - "এটি উইন্ডোজ পরিষেবাতে অনুরোধ করে, তবে শংসাপত্রগুলি যথাযথভাবে পাস করে না (পরিষেবাটি ব্যবহারকারীকে আইআইএস অ্যাপপ্লোল \ এএসপি.নেট as.০ হিসাবে রিপোর্ট করে)। এটি আমি যা করতে চাই তা নয় "
adrianbanks

4
এটি আমার সমস্যাটিকে ঠিক করতে পারে যেখানে iis কেবল উইন্ডোজ প্রমাণীকরণ সক্ষম করেছে। আপনার যদি কিছু বৈধ শংসাপত্রগুলি পাস করার প্রয়োজন হয় তবে এটি করা উচিত।
টিমমার্জ

নিশ্চিত নয় যে এটি ছদ্মবেশ / প্রতিনিধি দর্শন পরিস্থিতিতে ওয়েবক্লিয়েন্টের মতো একই কাজ করে same উপরের সমাধানটির সাথে এইচটিপিপ্লিয়েন্ট ব্যবহার করার সময় আমি "টার্গেটের মূল নামটি ভুল" পেয়েছি তবে একইরকম সেটআপ সহ ওয়েবক্লিয়েন্ট ব্যবহার করা ব্যবহারকারীর শংসাপত্রগুলি দিয়ে যায়।
পেডার রাইস

এটি আমার পক্ষে কাজ করেছে এবং লগগুলি সঠিক ব্যবহারকারীর দেখায়। যদিও ছবিতে ডাবল হপ রয়েছে, আমি এটি অন্তর্নিহিত প্রমাণীকরণ প্রকল্প হিসাবে এনটিএলএমের সাথে কাজ করার আশা করিনি, তবে এটি কার্যকর হয়।
নিতিন রাস্তোগি

এ্যাসনেট কোরের সর্বশেষতম সংস্করণটি ব্যবহার করে কীভাবে এটি করা যায়? (2.2)। যদি কেউ জানে ...
নিকো

26

আপনি যা করার চেষ্টা করছেন তা হ'ল এনটিএলএমটি পরিচয়টি পরবর্তী সার্ভারে প্রেরণ করা, যা এটি করতে পারে না - এটি কেবলমাত্র ছদ্মবেশ তৈরি করতে পারে যা আপনাকে কেবল স্থানীয় সংস্থানগুলিতে অ্যাক্সেস দেয়। এটি আপনাকে কোনও মেশিনের সীমানা অতিক্রম করতে দেবে না। কার্বেরোস প্রমাণীকরণ টিকিট ব্যবহার করে প্রতিনিধিদের (আপনার যা প্রয়োজন) সমর্থন করে এবং যখন চেইনের সমস্ত সার্ভার এবং অ্যাপ্লিকেশনগুলি সঠিকভাবে কনফিগার করা থাকে এবং ডোমেনে কার্বেরোস সঠিকভাবে সেট আপ করা হয় তখন টিকিটটি ফরোয়ার্ড করা যেতে পারে। সুতরাং, সংক্ষেপে আপনাকে এনটিএলএম ব্যবহার থেকে কেরবেরোসে পরিবর্তন করতে হবে।

আপনার কাছে উইন্ডোজ অনুমোদনের বিকল্পগুলি উপলভ্য এবং কীভাবে তারা কাজ করে সে সম্পর্কে আরও তথ্যের জন্য: http://msdn.microsoft.com/en-us/library/ff647076.aspx


3
" এনটিএলএমটি পরবর্তী সার্ভারে পরিচয় ফরোয়ার্ড করতে, যা এটি করতে পারে না " - ব্যবহার করার সময় এটি কীভাবে আসে WebClient? এই জিনিস আমি বুঝতে পারছি না - যদি এটা সম্ভব না হয়, তাহলে কিসের হয় করছিস নাকি?
অ্যাড্রিয়ানবঙ্কস

2
ওয়েব ক্লায়েন্ট ব্যবহার করার সময় এটি ক্লায়েন্ট এবং সার্ভারের মধ্যে এখনও কেবল একটি সংযোগ। এটি সেই সার্ভারে ব্যবহারকারীর ছদ্মবেশ তৈরি করতে পারে (1 হপ), তবে এই শংসাপত্রগুলি অন্য কোনও মেশিনে (2 হপস - ক্লায়েন্টকে সার্ভারে ২ য় সার্ভারে) ফরোয়ার্ড করতে পারে না। তার জন্য আপনার প্রতিনিধি দরকার need
ব্ল্যাকএসপি

1
আপনি যেভাবে চেষ্টা করছেন সেটি সম্পাদনের একমাত্র উপায় হ'ল ব্যবহারকারীকে আপনার এএসপি.নেট অ্যাপ্লিকেশনটির একটি কাস্টম ডায়ালগ বাক্সে তার ব্যবহারকারীর নাম এবং পাসওয়ার্ড টাইপ করতে, সেগুলি স্ট্রিং হিসাবে সংরক্ষণ করুন এবং তারপরে ব্যবহার করুন আপনি যখন আপনার ওয়েব এপিআই প্রকল্পের সাথে সংযুক্ত হন তখন সেগুলি আপনার পরিচয় সেট করতে। অন্যথায় আপনাকে এনটিএলএম ছাড়তে হবে এবং কার্বেরোসে চলে যেতে হবে, যাতে আপনি ওয়েব এপিআই প্রকল্পে কার্বেরোস টিকিটটি পাস করতে পারেন। আমি আমার মূল উত্তরের সাথে সংযুক্ত লিঙ্কটি খুব উচ্চারণে পড়ার পরামর্শ দিচ্ছি। আপনি যা করতে চেষ্টা করছেন তা শুরু করার আগে উইন্ডোজ প্রমাণীকরণের দৃ understanding় বোঝার প্রয়োজন।
ব্ল্যাকএসপি

2
@ ব্ল্যাকএসপি: উইন্ডোজ প্রমাণীকরণের সাথে আমার প্রচুর অভিজ্ঞতা আছে। আমি যা বোঝার চেষ্টা করছি তা কেন WebClientএনটিএলএম শংসাপত্রগুলি পাস করতে পারে তবে তা HttpClientপারে না the আমি একা এএসপি.নেট ছদ্মবেশ ব্যবহার করে এটি অর্জন করতে পারি, এবং কার্বেরোস ব্যবহার না করে বা ব্যবহারকারীর নাম / পাসওয়ার্ড সংরক্ষণ করতে পারি না। এটি তবে শুধুমাত্র কাজ করে WebClient
এড্রিয়ানবঙ্কস

1
পাঠ্য হিসাবে চারপাশে ব্যবহারকারীর নাম এবং পাসওয়ার্ড না দিয়ে 1 টিরও বেশি হপ জুড়ে ছদ্মবেশ তৈরি করা অসম্ভব। এটি ছদ্মবেশনের নিয়মগুলি ভঙ্গ করে এবং এনটিএলএম এটির অনুমতি দেয় না। ওয়েবক্লিয়েন্ট আপনাকে 1 হপ লাফিয়ে অনুমতি দেয় কারণ আপনি শংসাপত্রগুলি পাস করে বক্সে সেই ব্যবহারকারী হিসাবে চালান। আপনি যদি সুরক্ষা লগগুলি লক্ষ্য করেন তবে আপনি লগইন দেখতে পাবেন - ব্যবহারকারী সিস্টেমে লগইন করে। আপনি সেই মেশিন থেকে সেই ব্যবহারকারী হিসাবে চালাতে পারবেন না যদি না আপনি পাঠ্য হিসাবে শংসাপত্রগুলি পাস করেন এবং পরবর্তী বাক্সে লগ করতে অন্য ওয়েবক্লিয়েন্ট উদাহরণ ব্যবহার না করেন।
ব্ল্যাকএসপি

17

ঠিক আছে, সুতরাং উপরের সমস্ত অবদানকারীকে ধন্যবাদ। আমি .NET 4.6 ব্যবহার করছি এবং আমাদেরও একই সমস্যা ছিল। আমি ডিবাগিংয়ে System.Net.Httpবিশেষত: সময় ব্যয় করেছি HttpClientHandlerএবং নিম্নলিখিতগুলি পেয়েছি:

    if (ExecutionContext.IsFlowSuppressed())
    {
      IWebProxy webProxy = (IWebProxy) null;
      if (this.useProxy)
        webProxy = this.proxy ?? WebRequest.DefaultWebProxy;
      if (this.UseDefaultCredentials || this.Credentials != null || webProxy != null && webProxy.Credentials != null)
        this.SafeCaptureIdenity(state);
    }

সুতরাং ExecutionContext.IsFlowSuppressed()এই অপরাধী হতে পারে তা যাচাই করার পরে , আমি আমাদের ছদ্মবেশী কোডটি নিম্নরূপে গুটিয়ে রেখেছি:

using (((WindowsIdentity)ExecutionContext.Current.Identity).Impersonate())
using (System.Threading.ExecutionContext.SuppressFlow())
{
    // HttpClient code goes here!
}

এর ভিতরে কোড SafeCaptureIdenity(আমার বানান ভুল নয়) ধরে, WindowsIdentity.Current()যা আমাদের ছদ্মবেশী পরিচয়। এটি এখন নেওয়া হচ্ছে কারণ আমরা এখন প্রবাহকে দমন করছি। ব্যবহার / নিষ্পত্তি হবার কারণে এটি অনুরোধের পরে পুনরায় সেট করা হয়।

এটা এখন আমাদের জন্য কাজ বলে মনে হচ্ছে, ভাই!


2
এই বিশ্লেষণটি করার জন্য আপনাকে অনেক ধন্যবাদ। এটি আমার পরিস্থিতিও স্থির করেছে। এখন আমার পরিচয়টি অন্য ওয়েব অ্যাপ্লিকেশনটিতে সঠিকভাবে পার হয়ে গেছে! আপনি আমার কাজ ঘন্টা বাঁচাতে! আমি অবাক হয়েছি এটি টিক কাউন্টে বেশি নয়।
justdan23

আমার কেবল প্রয়োজন ছিল using (System.Threading.ExecutionContext.SuppressFlow())এবং বিষয়টি আমার জন্য সমাধান হয়ে গেল!
জেডএক্স

10

.NET কোর, আমি একটি পেতে পরিচালিত System.Net.Http.HttpClientসঙ্গে UseDefaultCredentials = trueব্যবহার করে একটি ফিরে শেষ সেবার অনুমোদিত ব্যবহারকারীর উইন্ডোজ পরিচয়পত্র মধ্য দিয়ে পাস করার WindowsIdentity.RunImpersonated

HttpClient client = new HttpClient(new HttpClientHandler { UseDefaultCredentials = true } );
HttpResponseMessage response = null;

if (identity is WindowsIdentity windowsIdentity)
{
    await WindowsIdentity.RunImpersonated(windowsIdentity.AccessToken, async () =>
    {
        var request = new HttpRequestMessage(HttpMethod.Get, url)
        response = await client.SendAsync(request);
    });
}

4

আমি উইন্ডোজ পরিষেবাতে ইন্টারনেট অ্যাক্সেস সহ কোনও ব্যবহারকারী সেট আপ করার পরে এটি আমার পক্ষে কাজ করেছিল।

আমার কোডে:

HttpClientHandler handler = new HttpClientHandler();
handler.Proxy = System.Net.WebRequest.DefaultWebProxy;
handler.Proxy.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
.....
HttpClient httpClient = new HttpClient(handler)
.... 

3

ঠিক আছে তাই আমি জোশাউনের কোড নিয়েছি এবং এটি জেনেরিক করেছি made আমি নিশ্চিত না যে আমার সিঙ্ক্রোনাসপোস্ট ক্লাসে সিঙ্গলটন প্যাটার্নটি প্রয়োগ করা উচিত। হয়তো আরও জ্ঞানী কেউ সাহায্য করতে পারেন।

বাস্তবায়ন

// আমি ধরে নিলাম আপনার নিজের কংক্রিটের ধরণ আছে। আমার ক্ষেত্রে আমি ফাইলক্যাটগরী নামে একটি শ্রেণীর সাথে কোডটি প্রথমে ব্যবহার করছি

FileCategory x = new FileCategory { CategoryName = "Some Bs"};
SynchronousPost<FileCategory>test= new SynchronousPost<FileCategory>();
test.PostEntity(x, "/api/ApiFileCategories"); 

জেনেরিক ক্লাস এখানে। আপনি যে কোন প্রকার পাস করতে পারেন

 public class SynchronousPost<T>where T :class
    {
        public SynchronousPost()
        {
            Client = new WebClient { UseDefaultCredentials = true };
        }

        public void PostEntity(T PostThis,string ApiControllerName)//The ApiController name should be "/api/MyName/"
        {
            //this just determines the root url. 
            Client.BaseAddress = string.Format(
         (
            System.Web.HttpContext.Current.Request.Url.Port != 80) ? "{0}://{1}:{2}" : "{0}://{1}",
            System.Web.HttpContext.Current.Request.Url.Scheme,
            System.Web.HttpContext.Current.Request.Url.Host,
            System.Web.HttpContext.Current.Request.Url.Port
           );
            Client.Headers.Add(HttpRequestHeader.ContentType, "application/json;charset=utf-8");
            Client.UploadData(
                                 ApiControllerName, "Post", 
                                 Encoding.UTF8.GetBytes
                                 (
                                    JsonConvert.SerializeObject(PostThis)
                                 )
                             );  
        }
        private WebClient Client  { get; set; }
    }

আপনি কৌতূহলী হলে আমার এপি ক্লাসগুলি এমন দেখাচ্ছে

public class ApiFileCategoriesController : ApiBaseController
{
    public ApiFileCategoriesController(IMshIntranetUnitOfWork unitOfWork)
    {
        UnitOfWork = unitOfWork;
    }

    public IEnumerable<FileCategory> GetFiles()
    {
        return UnitOfWork.FileCategories.GetAll().OrderBy(x=>x.CategoryName);
    }
    public FileCategory GetFile(int id)
    {
        return UnitOfWork.FileCategories.GetById(id);
    }
    //Post api/ApileFileCategories

    public HttpResponseMessage Post(FileCategory fileCategory)
    {
        UnitOfWork.FileCategories.Add(fileCategory);
        UnitOfWork.Commit(); 
        return new HttpResponseMessage();
    }
}

আমি নিিনজেক্ট, এবং কাজের ইউনিট সহ রেপো প্যাটার্ন ব্যবহার করছি। যাইহোক, উপরের জেনেরিক শ্রেণিটি সত্যই সহায়তা করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.