【问题标题】:Issues with Crypto.generateMac() in SalesForce APEXSalesForce APEX 中 Crypto.generateMac() 的问题
【发布时间】:2012-07-13 14:54:40
【问题描述】:

我们需要对使用 OAuth 1.0 并要求每个请求都使用 HMAC-SHA1 签名的服务进行一些标注。

该服务没有任何 APEX 客户端 API。因此,我们必须手动完成。

不幸的是,

EncodingUtil.base64Encode(Crypto.generateMac('hmacSHA1', Blob.valueOf(data), Blob.valueOf(key)));

返回一个与我们预期不同的字符串。我们将相同输入的输出与其他语言的库进行了比较。而且输出不一样。

【问题讨论】:

  • 你能举一个例子说明它有什么不同吗,它只是 base64 与十六进制编码?
  • 如果您提供一个您所看到的示例,那肯定会有所帮助:一个输入和两个不同的输出。我通过 Apex 使用 HmacSHA256 签名已经有一段时间了。

标签: oauth salesforce force.com


【解决方案1】:

调用 OAuth 1.0 没有问题。以下是一些用于签署您的请求的 Apex 示例:

编辑:添加了额外的代码

private Map<String,String> getUrlParams(String value) 
{
    Map<String,String> res = new Map<String,String>();
    if(value==null || value=='') 
    {
        return res;
    }
    for(String s : value.split('&')) 
    {
        List<String> kv = s.split('=');
        if(kv.size()>1) 
        {
            res.put(kv[0],kv[1]);
        }
    }
    return res;
}

private String createBaseString(Map<String,String> oauthParams, HttpRequest req) 
{
    Map<String,String> p = oauthParams.clone();
    if(req.getMethod().equalsIgnoreCase('post') && req.getBody()!=null && req.getHeader('Content-Type')=='application/x-www-form-urlencoded') 
        p.putAll(getUrlParams(req.getBody()));
    String host = req.getEndpoint();
    Integer n = host.indexOf('?');
    if(n > -1) 
    {
        p.putAll(getUrlParams(host.substring(n+1)));
        host = host.substring(0,n);
    }
    List<String> keys = new List<String>();
    keys.addAll(p.keySet());
    keys.sort();
    String s = keys.get(0)+'='+p.get(keys.get(0));
    for(Integer i=1; i<keys.size(); i++) 
        s = s + '&' + keys.get(i) + '=' + p.get(keys.get(i));

    return req.getMethod().toUpperCase() + '&' + EncodingUtil.urlEncode(host, 'UTF-8') + '&' + EncodingUtil.urlEncode(s, 'UTF-8');
}

public void sign(HttpRequest req) 
{
   nonce = String.valueOf(Crypto.getRandomLong());
   timestamp = String.valueOf(DateTime.now().getTime() / 1000);

   refreshParameters();

   String s = createBaseString(parameters, req);
   Blob sig = Crypto.generateMac('HmacSHA1', Blob.valueOf(s), 
      Blob.valueOf(consumerSecret+'&'+ (tokenSecret!=null ? tokenSecret : '')));

   signature = EncodingUtil.urlEncode(EncodingUtil.base64encode(sig), 'UTF-8');

   String header = 'OAuth ';
   for (String key : parameters.keySet()) 
   {
      header = header + key + '="'+parameters.get(key)+'", ';
   }
   header = header + 'oauth_signature="'+signature+'"';
   req.setHeader('Authorization',header);
}

这可能会达到,但是否存在区分大小写的问题?注意我叫'HmacSHA1'而不是'hmacSHA1'

【讨论】:

  • 嗨@adam,这很好,我正在尝试使用这个 generatemac 加密,我们如何使用我们自己的自定义私钥解密这个???可以发个示例代码吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多