代码之家  ›  专栏  ›  技术社区  ›  buru

验证来自Gmail上下文小工具的签名请求

  •  4
  • buru  · 技术社区  · 15 年前

    所以,我用 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
    根据Google的文档,请求由容器根据 OAuth signing process HMAC-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规范签署这个请求,但是签名不匹配。

    我已经尝试过使用两种不同的lib对请求进行签名:

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

    两个lib都生成相似的签名基字符串。然而,奇怪的是,它们会产生不同的签名,而且这些签名都与谷歌在oauth_signature param中发送的签名不匹配!

    各位小工具开发人员,我希望你们中有人比我幸运,并使这个签名验证方法起作用。拜托,告诉我我做错了什么。

    提前谢谢你,
    布鲁

    2 回复  |  直到 15 年前
        1
  •  1
  •   Daniel    14 年前

    我成功地使用了这个:

    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
  •  1
  •   0E322070    14 年前

    丹尼尔斯方法工作良好,只需一个小变化。

    • GetQueryParameters需要一个实现来检索所有查询参数。OAuthBase中的实现只返回那些没有前缀“oauth”的

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

    推荐文章