【问题标题】:Verifying signed requests from Gmail contextual gadget验证来自 Gmail 上下文小工具的签名请求
【发布时间】:2011-09-06 17:27:06
【问题描述】:

所以,我使用 gadgets.io.makeRequest(url, callback, params) 从 Gmail 上下文小工具发出请求,并在服务器端验证这些请求。

为了澄清,我在小工具端使用以下 makeRequest 参数:

params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.DOM;
params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.SIGNED;
params["OAUTH_SERVICE_NAME"] = "HMAC";
params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;

我从https://www.google.com/gadgets/directory/verify 获得了小工具的 consumerKey 和 consumerSecret
根据谷歌的文档,请求是由容器根据OAuth signing processHMAC-SHA1方法签名的。

在服务器端,我收到以下请求:

http://my.dev.machine.com/blapage.aspx?oauth_body_hash=2jmj7l5rSw0yVb/vlWAYkK/YBwk=&opensocial_owner_id=103030060674287937707&opensocial_viewer_id=103030060674287937707&opensocial_app_id=103129310198020657787&opensocial_app_url=http://my.dev.machine.com/gadget.xml&oauth_version=1.0&oauth_timestamp=1284403586&oauth_nonce=6436223395511631796&opensocial_container=http://mail.google.com&oauth_consumer_key=419336943235&oauth_signature_method=HMAC-SHA1&oauth_signature=bshZj9XOXECdYiyR1J8Etnadv5c=

然后我根据 Google 应该使用的相同 OAuth 规范签署此请求,但签名不匹配。

我已经尝试使用 2 个不同的库对请求进行签名:

  1. 我们自己开发的 .Net 库,用于对 Gmail IMAP OAuth 授权请求进行签名(它使用相同的签名方法,并且在那里工作得很好)。
  2. 贡献的 opensocial 库之一 (http://code.google.com/p/opensocial-net-client/)

两个库都产生相似的签名基本字符串。然而,奇怪的是,它们产生了不同的签名,并且这些签名都与谷歌在 oauth_signature 参数中发送的签名不匹配!

小工具开发人员,我希望你们中的某个人比我更幸运,并且使这种签名验证方法有效。请告诉我我在这里做错了什么。

提前致谢,
布鲁

【问题讨论】:

标签: c# asp.net oauth opensocial gmail-contextual-gadgets


【解决方案1】:

我成功使用了这个:

public Boolean ValidateSignature(String method, Uri url)
        {
            String normalizedUrl, normalizedRequestParameters;

            List<QueryParameter> parameters = new List<QueryParameter>();
            parameters.AddRange(GetQueryParameters(url.Query));

            var sigParam = parameters.Find(p => p.Name == OAuthSignatureKey);
            if (sigParam == null)
                return false;
            var expected = sigParam.Value;

            parameters.Remove(parameters.Find(p => p.Name == OAuthSignatureKey));
            parameters.Sort(new QueryParameterComparer());

            normalizedUrl = string.Format("{0}://{1}", url.Scheme, url.Host);
            if (!((url.Scheme == "http" && url.Port == 80) || (url.Scheme == "https" && url.Port == 443)))
            {
                normalizedUrl += ":" + url.Port;
            }
            normalizedUrl += url.AbsolutePath;
            normalizedRequestParameters = NormalizeRequestParameters(parameters);

            StringBuilder signatureBase = new StringBuilder();
            signatureBase.AppendFormat("{0}&", method.ToUpper());
            signatureBase.AppendFormat("{0}&", UrlEncode(normalizedUrl));
            signatureBase.AppendFormat("{0}", UrlEncode(normalizedRequestParameters));

            HMACSHA1 hmacsha1 = new HMACSHA1();
            hmacsha1.Key = Encoding.ASCII.GetBytes(string.Format("{0}&{1}", UrlEncode(ConsumerSecret), ""));//string.IsNullOrEmpty(tokenSecret) ? "" : UrlEncode(tokenSecret)));

            var computed = GenerateSignatureUsingHash(signatureBase.ToString(), hmacsha1);
            return expected == UrlEncode(computed);
        } 

连同您可以在此处找到的代码: http://oauth.googlecode.com/svn/code/csharp/OAuthBase.cs

编辑: 通过 get 或 post 发出请求和发送参数时,这不起作用。 问题似乎是Gmail对参数进行排序,大写字符在前。我只使用小写参数,但您可以轻松修复代码以确保大写在小写之前。

【讨论】:

    【解决方案2】:

    Daniels 方法只需稍加改动即可正常工作。

    • GetQueryParameters 需要一个实现来检索所有查询参数。 OAuthBase 中的实现只返回那些不以'oauth_'为前缀的

    我的主要问题是进行调用的小工具是使用 gadgets.io.makeRequest 到“http://myserver.com”,但处理页面是“http://myserver.com/default.aspx”。由于这种差异,签名未验证。使用 Gadget 中的 gadgets.io.makeRequest 调用“http://myserver.com/default.aspx”可以解决问题。

    【讨论】:

      猜你喜欢
      • 2015-06-28
      • 2011-03-24
      • 2015-07-07
      • 2017-09-09
      • 2016-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-25
      相关资源
      最近更新 更多