百度统计接口:登录接口,其实在数据查询时并不需要进行登录接口调用,但是需要提供百度统计账户、数据导出token、ucid(首次登录获取后存储在数据库中即可),百度接口文档中一般称之为“用户相关”。
今天我们看一下如何进行登录接口调用以及获取ucid
首先,查询百度统计登录接口文档DR-API
1
DR-API挂接方发送的消息应该遵循如下规范:
2
CLIENT ID ENCRYPT VERSION RESERVED RESERVED REAL DATA
3
每一个消息都包含了消息头和数据。消息头由8个字节组成,分成4个整数,每个整数包含2 个字节高位在前。
4
第一个整数表示client id,由DR-API统一分配。 第二个整数表示encrypt version,由DR-API统一分配。
5
第三个和第四个整数为保留整数,暂不使用。 消息头后面紧跟着消息数据。数据采用先压缩后加密的形式:
6
…
最初看到这个文档时,真的觉得很头大,不知道在干嘛,其中里面包含了三个接口方法,preLogin,verifyQuestion,doLogin,而我们只需要doLogin即可。参照官方提供的demo,我总结了以下几个步骤:
-
注册百度统计账户,确保网站昨日PV大于100,开通数据导出服务获得Token(好像有冷却时间,开通后不能立即用);
-
设置公钥key(我在项目中胡写的,但一直这么用没出啥问题),并进行RSA工具类获取公钥;
-
按照文档要求构造请求参数对象req(DoLoginRequestImpl);
-
将请求参数转换为json,并使用Gzip进行压缩;
-
通过RSA工具类用公钥加密数据,参数为第2步获取的公钥,第4步获取的string;
-
通过HTTP请求进行登录,返回结果数据;
-
解压返回结果。
分享测试代码:
01 /** 02 * 登陆接口 03 * 将登陆用户信息进行压缩加密,然后登陆 04 * @author shy 05 * @date 2016-11-15 下午01:08:44 06 */ 07 public static DoLoginResponse doLogin(WebsiteUser site) { 08 try { 09 DoLoginRequestImpl req = new DoLoginRequestImpl(); 10 req.setPassword(site.getPassword()); 11 req.setUsername(site.getUserName()); 12 req.setUuid(AppConstans.UUID); 13 req.setToken(site.getToken()); 14 req.setFunctionName(AppConstans.LOGIN_METHOD); 15
16 Key publicKey = RSAUtil.getPublicKey(AppConstans.KEY); 17 //System.out.println(“publicKey:” + publicKey ); 18 Gson gson = new Gson(); 19 String json = gson.toJson(req); 20 //System.out.println(“json:” + json); 21 byte[] bytes = RSAUtil.encryptByPublicKey(GZipUtil.gzipString(json), publicKey); 22 //System.out.println(“zip:” + bytes.length); 23 String loginResult = HttpClientUtils.doHttpPost(AppConstans.HOME_LOGIN_ADDRESS, bytes, 10000, “utf-8”); 24 DoLoginResponse resp = gson.fromJson(loginResult, DoLoginResponse.class); 25 return resp; 26
27 } catch (Exception e) { 28 // TODO Auto-generated catch block 29 e.printStackTrace(); 30 } 31 return null; 32 } HTTP请求也比较特殊
01 /** 02 * 仅用于登陆的http post请求,登陆返回结果需要解压,然后才可以返回String或者obj 03 * @param url 04 * @param bytes 05 * @param timeout 06 * @param encode 07 * @return 08 * @author shy 09 * @date 2016-11-15 下午01:26:48 10 */ 11 public static String doHttpPost(String url, byte[] bytes, int timeout, String encode){ 12 HttpClient httpClient = new HttpClient(new HttpClientParams(), new SimpleHttpConnectionManager()); 13 httpClient.getParams().setContentCharset(encode); 14 PostMethod postMethod = new PostMethod(url); 15 InputStream inputStream = new ByteArrayInputStream(bytes, 0, bytes.length); 16 RequestEntity requestEntity = new InputStreamRequestEntity(inputStream, bytes.length, “text/json; charset=utf-8”); 17 postMethod.setRequestEntity(requestEntity); 18 postMethod.addRequestHeader(“Content-Type”, “text/json; charset=utf-8”); 19 postMethod.addRequestHeader(“uuid”, AppConstans.UUID); 20 postMethod.addRequestHeader(“account_type”, “1”); //默认是百度账号 21 try { 22 httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(timeout); 23
24 int num = httpClient.executeMethod(postMethod); 25 //System.out.println(num); 26 if (num == AppConstans.SC_OK) { 27 //System.out.println(postMethod.getResponseBodyAsString()); 28 InputStream in = postMethod.getResponseBodyAsStream(); 29 try { 30 byte[] b = new byte[8]; 31 if (in.read(b) != 8) { 32 throw new ClientInternalException(“Server response is invalid.”); 33 } 34 if (b[1] != 0) { 35 throw new ClientInternalException("Server returned an error code: " + b[0]+b[1]+b[2]+b[3]+b[4]+b[5]+b[6]+b[7]); 36 } 37 int total = 0, k = 0; 38 b = new byte[AppConstans.MAX_MSG_SIZE]; 39 while (total < AppConstans.MAX_MSG_SIZE) { 40 k = in.read(b, total, AppConstans.MAX_MSG_SIZE - total); 41 if (k < 0) 42 break; 43 total += k; 44 } 45 if (total == AppConstans.MAX_MSG_SIZE) { 46 throw new ClientInternalException(“Server returned message too large.”); 47 } 48 byte[] zip = ArrayUtils.subarray(b, 0, total); 49 zip = GZipUtil.unGzip(zip); 50 //System.out.println(JacksonUtil.str2Obj(new String(zip, “UTF-8”), DoLoginResponse.class)); 51 //return JacksonUtil.str2Obj(new String(zip, “UTF-8”), DoLoginResponse.class); 52 return new String(zip, “UTF-8”); 53 } catch (IOException e) { 54 throw new ClientInternalException(e); 55 } finally { 56 if (in != null) { 57 try { 58 in.close(); 59 } catch (IOException e) { 60 throw new ClientInternalException(e); 61 } 62 } 63 } 64 } 65 } catch (Exception e) { 66 //logger.error(e.getMessage(), e); 67 } finally { 68 postMethod.releaseConnection(); 69 } 70 return “”; 71 } 请求参数相关实体类DoLoginRequestImpl
DoLoginRequestImpl.txt
请求参数相关实体类AbstractLoginRequest
AbstractLoginRequest.txt
两个官方提供的工具类 RSAUtil,GzipUtil
GZipUtil.txt
RSAUtil.txt
几个请求方法路径参数,两个胡写的key,uuid
1
public static final String HOME_LOGIN_ADDRESS = “https://api.baidu.com/sem/common/HolmesLoginService”;
2
public static final String LOGIN_METHOD = “doLogin”;
3
public static final String KEY = “MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHn/hfvTLRXViBXTmBhNYEIJeGGGDkmrYBxCRelriLEYEcrwWrzp0au9nEISpjMlXeEW4+T82bCM22+JUXZpIga5qdBrPkjU08Ktf5n7Nsd7n9ZeI0YoAKCub3ulVExcxGeS3RVxFai9ozERlavpoTOdUzEH6YWHP4reFfpMpLzwIDAQAB”;
4
public static final String UUID = “MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBg-1”;
5
public static final String ENCODING = “UTF-8”;
6
public static final String KEY_ALGORITHM = “RSA”;
本地测试结果
1 publicKey:Sun RSA public key, 1024 bits 2 modulus: 140181360492363042093064629109168807058601283712538405681407110724656257746707446709576724699949199331786898836532551899046132726873049289034928462964377304267872154683916692441298827083987020018969530763815538492523273482363822189405756057227531045360665993857388167087281300717732444075072406512231372180431 3 public exponent: 65537 4 json:{“request”:{“password”:"******"},“username”:“rhhz1”,“token”:“904cfbbc6fdc894d91e35b50fa036d8a”,“functionName”:“doLogin”,“uuid”:“MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBg-1”} 5 zip:256 6 {“retcode”:0,“retmsg”:“成功”,“ucid”:23881277,“st”:“8b3f013d045f6139b15b797e5c6a01cc709797379f84c37d4258e7269026864b51583989641952d80c53bac5”,“istoken”:0,“setpin”:0,“questions”:null} 分享源码,点击下载