qq登陆sig错误问题-5:signature verification failed 生成sig
本文章为原创文章,转载请标明出处,有问题敬请联系我。我的账号有联系方式
问题原因:由于qq获取信息时,需要根据数据动态生成sig,由于在生成sig时会一个不小心就生成错误的sig
以获取qq用户信息为例,有两个步骤:
- qq登陆
- 获取信息
在获取信息时可能会遇到-5:signature verification failed 问题
现在来生成在sig,我会提出一些要注意的地方从而生成正确的sig
生成四个的步骤:
- Step 1. 构造源串
- * 第1步:将请求的URI路径进行URL编码,*
- * 第2步:将除“sig”外的所有参数按key进行字典升序排列*
- * 第3步:将第2步中排序后的参数(key=value)用&拼接起来*
- * 第4步:将HTTP请求方式,第1步以及第3步中的到的字符串用&拼接起来,得到源串*
- Step 2. 构造密钥
- Step 3. 生成签名值
代码案例:
import android.util.Base64;
import android.util.Log;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
/**
* Created by ancode on 2017/9/15.
*/
public class CreatSignature_HMAC_SHA1 {
private static String sig;
private static String source;//被加密的原串
private static String key;//用于加密
public static String getSig(String openid, String openkey) {
String tempuri;
String format = "json";
String pf = "qzone";
String userip = "10.0.0.1";
// String mopenid = "";
// String mopenkey = "";
try {
/*
* Step 1. 构造源串
*
*/
// 第1步:将请求的URI路径进行URL编码,得到: %2Fv3%2Fuser%2Fget_info
tempuri = URLEncoder.encode(QQConstants.GET_USER_INFO, "UTF-8");
Log.d("showhmacsha1", tempuri);
// 第2步:将除“sig”外的所有参数按key进行字典升序排列,排列结果为:appid,format,openid,openkey,pf,userip
// 第3步:将第2步中排序后的参数(key=value)用&拼接起来:
// appid=123456&format=json&openid=11111111111111111&openkey=2222222222222222&pf=qzone&userip=112.90.139.30
// 然后进行URL编码( 编码时请关注URL编码注意事项,否则容易导致后面签名不能通过验证),编码结果为:
// appid%3D123456%26format%3Djson%26openid%3D11111111111111111%26openkey%3D2222222222222222%26pf%3Dqzone%26
// userip%3D112.90.139.30
String tempStr = "appid=" + QQConstants.QQ_APP_ID + "&" + "format=" + format + "&" + "openid=" + openid + "&" + "openkey=" + openkey + "&" + "pf=" + pf + "&" + "userip=" + userip;
Log.d("showhmacsha1", tempStr);
tempStr = URLEncoder.encode(tempStr, "UTF-8");
Log.d("showhmacsha1", tempStr);
// 第4步:将HTTP请求方式,第1步以及第3步中的到的字符串用&拼接起来,得到源串:
// GET&%2Fv3%2Fuser%2Fget_info&appid%3D123456%26format%3Djson%26openid%3D11111111111111111%26
// openkey%3D2222222222222222%26pf%3Dqzone%26userip%3D112.90.139.30
source = "GET&" + tempuri + "&" + tempStr;
} catch (Exception e) {
Log.e("showhmacsha1", e.getMessage());
}
/*
* Step 2. 构造密钥
* 得到密钥的方式:在应用的appkey末尾加上一个字节的“&”,即appkey&
*/
key = QQConstants.QQ_APP_KEY + "&";
/*
* Step 3. 生成签名值
* 使用加密算法加密
*/
sig = hmacSha1(source, key);
Log.e("showhmacsha1", sig);
/*
* Step 4. 返回sig
*
*/
return sig;
}
public static String hmacSha1(String base, String key) {
try {
Mac mac = Mac.getInstance("HmacSHA1");
SecretKeySpec secret = new SecretKeySpec(key.getBytes("UTF-8"), mac.getAlgorithm());
mac.init(secret);
return Base64.encodeToString(mac.doFinal(base.getBytes()), Base64.NO_WRAP);
} catch (NoSuchAlgorithmException e) {
Log.e("showhmacsha1", "Hash algorithm SHA-1 is not supported", e);
} catch (UnsupportedEncodingException e) {
Log.e("showhmacsha1", "Encoding UTF-8 is not supported", e);
} catch (InvalidKeyException e) {
Log.e("showhmacsha1", "Invalid key", e);
}
return "";
}
}
注意的问题:
- uri怎么知道
- http://wiki.open.qq.com/wiki/API%E5%88%97%E8%A1%A8
- url是什么
- http://wiki.open.qq.com/wiki/API3.0%E6%96%87%E6%A1%A3#.E8.AF.B7.E6.B1.82URL.E8.AF.B4.E6.98.8E
- 要url编码的地方一定要编码
- 第三步一定是key+value用&链接
- 第4步一定是 请求方式+第一步+第三步
- 使用HmacSHA1加密算法
- appid 和 appkey 要换成自己申请的