文档 下载安装 商店 博客 问答 主机

magento1.x 身份认证时报签名错误

oauth

#1

根据文档,签名基本字符串形成为:

HTTP_METHOD&urlencode(BASE_URL_OF_RESOURCE)&urlencode(PARAMETERS_ORDERED_AND_NORMALIZED_AND_WITHOUT_OAUTHSIGNATURE)

用于维护的密钥是:
urlencode(CONSUMER_SECRET)&urlencode(OAUTH_TOKEN_SECRET) - 当你有一个令牌密钥
urlencode(CONSUMER_SECRET)& - 当你没有令牌密钥时(在请求一个“请求令牌”时一开始)
我的签名字符串也是按照这样生成的但是认证时一直都是报错:oauth_problem=signature_invalid
参与签名的参数和代码如下截图,哪位大神能看下是哪里有问题


#2

这个错误产生的原因是因为客户端生成的signature与Magento生成的signature不匹配,抛出的错误.
请首先确保已经对参数进行了解码,及使用相同的签名加密方法.

搜索了一下,看看这个回答,或许能帮助到你:

另外,代码最好不要使用图片,看不清楚,也不能复制。
本编辑器支持代码高亮,
直接复制代码至编辑器,然后在代码前加入一个回车,并保证每行代码前至少有四个空格。
类似:

public function newAction() {
	$this->_forward('edit');
}

public function gridAction()
{
    $this->loadLayout();
    $this->getResponse()->setBody($this->getLayout()->createBlock('banners/adminhtml_banners_grid')->toHtml());
}

magento 签名
#4

谢谢你的回答,以后提问会注意的!下面是我进行身份认证第一步获取requestToken的代码(两个个发送请求的工具类HttpClientUtil和SSLClient,一个主类TestMain ),现在的问题是报签名错误,麻烦你看下我代码哪里写的不对

	/**
	 * SSLClient类的代码
	 */
	import java.security.cert.CertificateException;  
	import java.security.cert.X509Certificate;  
	import javax.net.ssl.SSLContext;  
	import javax.net.ssl.TrustManager;  
	import javax.net.ssl.X509TrustManager;  
	import org.apache.http.conn.ClientConnectionManager;  
	import org.apache.http.conn.scheme.Scheme;  
	import org.apache.http.conn.scheme.SchemeRegistry;  
	import org.apache.http.conn.ssl.SSLSocketFactory;  
	import org.apache.http.impl.client.DefaultHttpClient;  

	public class SSLClient extends DefaultHttpClient{  
	    public SSLClient() throws Exception{  
	        SSLContext ctx = SSLContext.getInstance("TLS");  
	        X509TrustManager tm = new X509TrustManager() {  
	                @Override  
	                public void checkClientTrusted(X509Certificate[] chain,  
	                        String authType) throws CertificateException {  
	                }  
	                @Override  
	                public void checkServerTrusted(X509Certificate[] chain,  
	                        String authType) throws CertificateException {  
	                }  
	                @Override  
	                public X509Certificate[] getAcceptedIssuers() {  
	                    return null;  
	                }  
	        };  
	        ctx.init(null, new TrustManager[]{tm}, null);  
	        SSLSocketFactory ssf = new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);  
	        ClientConnectionManager ccm = this.getConnectionManager();  
	        SchemeRegistry sr = ccm.getSchemeRegistry();  
	        sr.register(new Scheme("https", 443, ssf));  
	    }  
	}  


	/**
	 * HttpClientUtil类的代码
	 */
            import java.util.ArrayList;  
	import java.util.Iterator;  
	import java.util.List;  
	import java.util.Map;  
	import java.util.Map.Entry;  
	import org.apache.http.HttpEntity;  
	import org.apache.http.HttpResponse;  
	import org.apache.http.NameValuePair;  
	import org.apache.http.client.HttpClient;  
	import org.apache.http.client.entity.UrlEncodedFormEntity;  
	import org.apache.http.client.methods.HttpPost;  
	import org.apache.http.message.BasicNameValuePair;  
	import org.apache.http.util.EntityUtils;
	
	
	public class HttpClientUtil {  
	    public String doPost(String url,Map<String,String> map,String charset){  
	        HttpClient httpClient = null;  
	        HttpPost httpPost = null;  
	        String result = null;  
	        try{  
	            httpClient = new SSLClient();  
	            httpPost = new HttpPost(url);  
	            //  
	            List<NameValuePair> list = new ArrayList<NameValuePair>();  
	            Iterator iterator = map.entrySet().iterator();  
	            while(iterator.hasNext()){  
	                Entry<String,String> entry = (Entry<String, String>) iterator.next();  
	                list.add(new BasicNameValuePair(entry.getKey(),entry.getValue()));  
	            }  
	            if(list.size() > 0){  
	                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list,charset);  
	                httpPost.setEntity(entity);  
	            }  
	            HttpResponse response = httpClient.execute(httpPost);  
	            if(response != null){  
	                HttpEntity resEntity = response.getEntity();  
	                if(resEntity != null){  
	                    result = EntityUtils.toString(resEntity,charset);  
	                }  
	            }  
	        }catch(Exception ex){  
	            ex.printStackTrace();  
	        }  
	        return result;  
	    }  
	}


	/**
	 * TestMain类的代码
	 */
            import java.net.URLEncoder;
	import java.util.ArrayList;
	import java.util.Collection;
	import java.util.Collections;
	import java.util.Date;
	import java.util.HashMap;
	import java.util.List;
	import java.util.Map;
	import java.util.UUID;
	import javax.crypto.Mac;
	import javax.crypto.spec.SecretKeySpec;
	import org.apache.commons.codec.binary.Base64;  
	//
	public class TestMain {  
	    private String charset = "utf-8";  
	    private HttpClientUtil httpClientUtil = null;
		//获取签名的方法  
		public static String getSign(String url,Map<String, String> map) {
			// TODO Auto-generated method stub
			Collection<String> keyset = map.keySet();
			List<String> list = new ArrayList<String>(keyset);
			//对参与签名的参数和值进行排序和拼接
			Collections.sort(list);		
			StringBuffer sb = new StringBuffer();
			for (String string : list) {
				sb.append(URLEncoder.encode(string)+"="+URLEncoder.encode(map.get(string))+"&");
			}
			String baseStr = sb.toString();
			baseStr = baseStr.substring(0, baseStr.length()-1);
			System.out.println("baseStr is"+baseStr);
			//对拼接好的字符串进行URLEncoder进行编码
			String baseEncode = URLEncoder.encode(baseStr);
			System.out.println("baseEncode value is--->"+baseEncode);
			//把请求方式,url,参数字符串拼接成进行签名的字符串
			String signStr = "POST&"+URLEncoder.encode(url)+"&"+baseEncode;
			//进行HMAC-SHA1加密
			try {
				signStr = getSignature(signStr,URLEncoder.encode("151305abc553966ebe3878f964dc1568")+"&" );
				byte[] encodeBase64 = Base64.encodeBase64(signStr.getBytes("UTF-8"));  
				signStr = new String(encodeBase64);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			System.out.println("签名的最终字符串是--------->"+signStr);
			String signResult = signStr;
			return signResult;
		}
	
		public static String byte2hex(byte[] b) 
		{
		    StringBuilder hs = new StringBuilder();
		    String stmp;
		    for (int n = 0; b!=null && n < b.length; n++) {
		        stmp = Integer.toHexString(b[n] & 0XFF);
		        if (stmp.length() == 1)
		            hs.append('0');
		        hs.append(stmp);
		    }
		    return hs.toString().toUpperCase();
		}
		
		 public static String getSignature(String data, String key) throws Exception {
		        byte[] keyBytes = key.getBytes();
		        SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA1");
		        Mac mac = Mac.getInstance("HmacSHA1");
		        mac.init(signingKey);
		        byte[] rawHmac = mac.doFinal(data.getBytes());
		        StringBuilder sb = new StringBuilder();
		        for (byte b : rawHmac) {
		            sb.append(byteToHexString(b));
		        }
		        return sb.toString();
		    }
	
		    private static String byteToHexString(byte ib) {
		        char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
		        char[] ob = new char[2];
		        ob[0] = Digit[(ib >>> 4) & 0X0f];
		        ob[1] = Digit[ib & 0X0F];
		        return new String(ob);
		    }
	    
	    public TestMain(){  
	        httpClientUtil = new HttpClientUtil();  
	    }  
	      
	    public void test(){ 
	    	String oauth_callback = "http://127.0.0.1:8080/kdoms_site/rest/test/trade/getCode";
	    	//BASE_URL
	    	String baseUrl = "http://192.168.66.248/magento";
		//发送请求的url
		String url = "http://192.168.66.248/magento/oauth/initiate?oauth_callback="+URLEncoder.encode(oauth_callback);
	        Map<String, String> signMap = new HashMap<String, String>();
		//参与签名的参数
		signMap.put("oauth_callback", "http://127.0.0.1:8080/kdoms_site/rest/test/trade/getCode");
		signMap.put("oauth_consumer_key", "09e01478682cbdd668e8927e16f78663");
		String oauth_nonce = UUID.randomUUID().toString().replaceAll("-", "");
		//System.out.println("oauth_nonce is --->"+oauth_nonce);
		signMap.put("oauth_nonce", oauth_nonce);
		signMap.put("oauth_signature_method", "HMAC-SHA1");
		signMap.put("oauth_timestamp", String.valueOf(new Date().getTime()/1000));
		signMap.put("oauth_version", "1.0"); 
		String sign = getSign(baseUrl+"/oauth/initiate", signMap);
		//把得到的签名放入,requestToken请求参数就都有了
		signMap.put("oauth_signature", sign);
		//发送请求
	        String reponseStr = httpClientUtil.doPost(url,signMap,charset);  
	        System.out.println("result:"+reponseStr);  
	    }  
	      
	    public static void main(String[] args){  
	        TestMain main = new TestMain();  
	        main.test();  
	    }  
	}

#5

java我不懂,不过你的代码里,测试的url明明是http协议,为什么还要用SSL?

    public SSLClient() throws Exception{  
        SSLContext ctx = SSLContext.getInstance("TLS");  
        X509TrustManager tm = new X509TrustManager() {  
                @Override  
                public void checkClientTrusted(X509Certificate[] chain,  
                        String authType) throws CertificateException {  
                }  
                @Override  
                public void checkServerTrusted(X509Certificate[] chain,  
                        String authType) throws CertificateException {  
                }  
                @Override  
                public X509Certificate[] getAcceptedIssuers() {  
                    return null;  
                }  
        };  
        ctx.init(null, new TrustManager[]{tm}, null);  
        SSLSocketFactory ssf = new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);  
        ClientConnectionManager ccm = this.getConnectionManager();  
        SchemeRegistry sr = ccm.getSchemeRegistry();  
        sr.register(new Scheme("https", 443, ssf));  
    }  

http://127.0.0.1:8080/


#6

好吧,SSLClient是一个继承了实现了HttpClient接口类的类。再请教您一个问题,我这边发送过去的签名最终会在magento的Server.php里面进行校验,应该是这段代码,想知道签名的步骤和$util->sign这个方法的实现在哪里。

protected function _validateSignature()
    {
       $util = new Zend_Oauth_Http_Utility();

         $calculatedSign = $util->sign(
        array_merge($this->_params, $this->_protocolParams),
        $this->_protocolParams['oauth_signature_method'],
        $this->_consumer->getSecret(),
        $this->_token->getSecret(),
        $this->_request->getMethod(),
        $this->_request->getScheme() . '://' . $this->_request->getHttpHost() . $this->_request->getRequestUri()
    );

	if ($calculatedSign != $this->_protocolParams['oauth_signature']) {
        $this->_throwException('', self::ERR_SIGNATURE_INVALID);
    }
    
}


#7

实现在哪里?不明白你的意思。
你在php端,打印一下这个方法看看有没有你想要的东西:

<?php var_dump($util->sign()->getData());

#8

已解决,谢谢你了:slight_smile: