草庐IT

c# - 为什么我的 REST 服务 .NET 客户端会发送每个没有身份验证 header 的请求,然后使用身份验证 header 重试?

coder 2024-05-19 原文

我们碰巧运行一个带有 API 的 REST 网络服务,要求客户端使用基本 身份验证。我们用各种语言制作了一组简洁的示例,展示了如何与我们的服务进行交互。现在,我正在查看该服务的 IIS 日志,发现以下模式经常发生:

  • 一个请求来了,被 HTTP 代码 401 拒绝
  • 同样的请求被重新发送并成功

看起来第一个请求发送时没有Authorization header ,然后第二个请求使用正确的 header 发送并成功。大多数情况下,日志记录包含“user-agent”,这与我们在 .NET 示例中植入的字符串相同。

所以我认为问题仅出在 .NET 程序上。我们的示例代码没有重现该问题,因此我假设用户以某种方式修改了代码或从头开始编写了自己的代码。

我们尝试联系用户,但显然他们不想投入时间进行研究。因此,最好找出导致 .NET 程序出现这种行为的最可能情况。

他们为什么要这样做?为什么他们不在第一次尝试时附加标题?

最佳答案

这是 HttpClientHttpWebRequest 类的默认行为,它们通过以下方式公开。

注意:下面的文字解释了导致问题中描述的问题的次优行为。您很可能不应该这样编写代码。而是在下方滚动到更正后的代码

在这两种情况下,实例化一个 NetworkCredenatial 对象并在其中设置用户名和密码

var credentials = new NetworkCredential( username, password );

如果您使用 HttpWebRequest - 设置 .Credentials 属性:

webRequest.Credentials = credentials;

如果您使用 HttpClient - 将凭据对象传递到 HttpClientHandler(来自 here 的更改代码):

var client = new HttpClient(new HttpClientHandler() { Credentials = credentials })

然后运行Fiddler,开始请求。您将看到以下内容:

  • 发送的请求没有授权 header
  • 服务回复 HTTP 401 和WWW-Authenticate: Basic realm="UrRealmHere"
  • 使用正确的Authorization header 重新发送请求(并成功)

解释了此行为 here - 客户端事先不知道服务需要Basic 并尝试协商身份验证协议(protocol)(如果服务需要Digest 发送Basic 打开的 header 是无用的,可能会危及客户端)。

注意:此处对次优行为的解释结束,并解释了更好的方法。您很可能应该使用下面的代码而不是上面的代码。

对于已知服务需要基本的情况,可以通过以下方式消除额外请求:

不要设置 .Credentials,而是使用 here 中的代码手动添加 header .对用户名和密码进行编码:

var encoded = Convert.ToBase64String( Encoding.ASCII.GetBytes(
    String.Format( "{0}:{1}", username, password ) ) );

当使用 HttpWebRequest 时,将其添加到 header 中:

request.Headers.Add( "Authorization", "Basic " + encoded );

并且在使用 HttpClient 时将其添加到默认 header 中:

client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue( "Basic", encoded );

当您这样做时,每次都会发送带有正确授权 header 的请求。请注意,您不应设置.Credentials,否则如果用户名或密码错误,相同的请求将被发送两次,但两次都是错误的凭据和两次当然都会产生 HTTP 401。

关于c# - 为什么我的 REST 服务 .NET 客户端会发送每个没有身份验证 header 的请求,然后使用身份验证 header 重试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25761214/

有关c# - 为什么我的 REST 服务 .NET 客户端会发送每个没有身份验证 header 的请求,然后使用身份验证 header 重试?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  3. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  4. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  5. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  6. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  7. ruby - 难道Lua没有和Ruby的method_missing相媲美的东西吗? - 2

    我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/

  8. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  9. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  10. ruby-on-rails - rails 目前在重启后没有安装 - 2

    我有一个奇怪的问题:我在rvm上安装了ruby​​onrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(

随机推荐