jjzjj

c# - 使用 HMAC-SHA1 加密创建 OAuth 签名返回 HTTP 401

coder 2024-05-30 原文

问题
我需要对需要 OAuth 加密的 API 进行身份验证。

我的方向是正确的,但我确信我的签名基本字符串有问题。由于 HMACSHA1 哈希基于 key 和 BaseString,因此我得到了错误的 oauth_signature。

OAuth Signing Process

到目前为止
我已经能够收集到所有必需的数据,其中包括:

  • Consumer Key
  • Consumer Secret
  • Acces Token
  • Acces Secret
  • Sha1Hased Value (Based on Key and Message, where Message is the signature Base string)
  • Signature Base String

问题
由于签名无效,我收到 HTTP(401 错误请求)返回。

注意:我很确定这是我构建签名基础字符串的方式。有关我使用的 API 文档的信息,请查看底部页面。

代码

GetOAuthToken(执行实际请求)

public static string GetAuthorizationToken()
{
    string TimeInSecondsSince1970 = ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString();
    string Nonce = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(TimeInSecondsSince1970
    + TimeInSecondsSince1970 + TimeInSecondsSince1970));
    HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(GetAppleApiUrl.GetUrl(AppleApiUrl.SESSION_TOKEN));
    httpWebRequest.Method = "GET";

    string consumer_secret = Uri.EscapeDataString(Settings.SettingsManager.consumer_secret);
    string token_secret = Uri.EscapeDataString(Settings.SettingsManager.access_secret);

    string signature_base_string = GetSignatureBaseString(TimeInSecondsSince1970, Nonce);
    string SHA1HASH = GetSha1Hash(consumer_secret + "&" + token_secret, signature_base_string);
                
    string Header =
       "OAuth realm=" + '"' + "ADM" + '"' + "," +
       "oauth_consumer_key=" + '"' + Settings.SettingsManager.consumer_key + '"' + "," +
       "oauth_token=" + '"' + Settings.SettingsManager.access_token + '"' + "," +
       "oauth_signature_method=" + '"' + "HMAC-SHA1" + '"' + "," +
       "oauth_signature= " + '"' + SHA1HASH + '"' + "," + 
       "oauth_timestamp=" + '"' + TimeInSecondsSince1970 + '"' + "," +
       "oauth_nonce=" + '"' + Nonce + '"' + "," +
       "oauth_version=" + '"' + "1.0" + '"' + ",";
   
    httpWebRequest.Headers.Add(HttpRequestHeader.Authorization, Header);
    var Result = httpWebRequest.GetResponse();

    return Result.ToString();
}

GetSha1Hash

public static string GetSha1Hash(string key, string message)
{
    var encoding = new System.Text.ASCIIEncoding();

    byte[] keyBytes = encoding.GetBytes(key);
    byte[] messageBytes = encoding.GetBytes(message);

    string Sha1Result = string.Empty;

    using (HMACSHA1 SHA1 = new HMACSHA1(keyBytes))
    {
        var Hashed = SHA1.ComputeHash(messageBytes);
        Sha1Result = Convert.ToBase64String(Hashed);
    }

    return Sha1Result;
}

GetSignatureBaseString

public static string GetSignatureBaseString(string TimeStamp, string Nonce)
{
    //1.Convert the HTTP Method to uppercase and set the output string equal to this value.
    string Signature_Base_String = "Get";
    Signature_Base_String = Signature_Base_String.ToUpper();

    //2.Append the ‘&’ character to the output string.
    Signature_Base_String = Signature_Base_String + "&";

    //3.Percent encode the URL and append it to the output string.
    string PercentEncodedURL = Uri.EscapeDataString(GetAppleApiUrl.GetUrl(AppleApiUrl.SESSION_TOKEN));
    Signature_Base_String = Signature_Base_String + PercentEncodedURL;

    //4.Append the ‘&’ character to the output string.
    Signature_Base_String = Signature_Base_String + "&";

    //5.append parameter string to the output string.
    Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("oauth_consumer_key=" + Settings.SettingsManager.consumer_key);
    Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("&oauth_token=" + Settings.SettingsManager.access_token);
    Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("&oauth_signature_method=" +"HMAC-SHA1");
    Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("&oauth_timestamp=" + TimeStamp);
    Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("&oauth_nonce=" + Nonce);
    Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("&oauth_version=" + "1.0");

    return Signature_Base_String;
}

结果(Fiddler)

API 文档

最佳答案

看起来您应该在 Header 字符串和 GetSignatureBaseString 方法中按字母顺序对参数进行排序,如 this comment 中所述和 Twitter OAuth documentation

关于c# - 使用 HMAC-SHA1 加密创建 OAuth 签名返回 HTTP 401,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30706133/

有关c# - 使用 HMAC-SHA1 加密创建 OAuth 签名返回 HTTP 401的更多相关文章

  1. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  2. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  3. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  4. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  5. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  6. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  7. ruby-on-rails - Rails - 从命名路由中提取 HTTP 动词 - 2

    Rails中有没有一种方法可以提取与路由关联的HTTP动词?例如,给定这样的路线:将“users”匹配到:“users#show”,通过:[:get,:post]我能实现这样的目标吗?users_path.respond_to?(:get)(显然#respond_to不是正确的方法)我最接近的是通过执行以下操作,但它似乎并不令人满意。Rails.application.routes.routes.named_routes["users"].constraints[:request_method]#=>/^GET$/对于上下文,我有一个设置cookie然后执行redirect_to:ba

  8. ruby-on-rails - Heroku 吃掉了我的自定义 HTTP header - 2

    我正在使用Heroku(heroku.com)来部署我的Rails应用程序,并且正在构建一个iPhone客户端来与之交互。我的目的是将手机的唯一设备标识符作为HTTPheader传递给应用程序以进行身份​​验证。当我在本地测试时,我的header通过得很好,但在Heroku上它似乎去掉了我的自定义header。我用ruby​​脚本验证:url=URI.parse('http://#{myapp}.heroku.com/')#url=URI.parse('http://localhost:3000/')req=Net::HTTP::Post.new(url.path)#boguspara

  9. ruby-on-rails - 使用 HTTP.get_response 检索 Facebook 访问 token 时出现 Rails EOF 错误 - 2

    我试图在我的网站上实现使用Facebook登录功能,但在尝试从Facebook取回访问token时遇到障碍。这是我的代码:ifparams[:error_reason]=="user_denied"thenflash[:error]="TologinwithFacebook,youmustclick'Allow'toletthesiteaccessyourinformation"redirect_to:loginelsifparams[:code]thentoken_uri=URI.parse("https://graph.facebook.com/oauth/access_token

  10. ruby - HTTP 请求中的用户代理,Ruby - 2

    我是Ruby的新手。我试过查看在线文档,但没有找到任何有效的方法。我想在以下HTTP请求botget_response()和get()中包含一个用户代理。有人可以指出我正确的方向吗?#PreliminarycheckthatProggitisupcheck=Net::HTTP.get_response(URI.parse(proggit_url))ifcheck.code!="200"puts"ErrorcontactingProggit"returnend#Attempttogetthejsonresponse=Net::HTTP.get(URI.parse(proggit_url)

随机推荐