`

百度云推送javasdk诞生记之签名算法实现

阅读更多

        在实现之初,就遇到一个麻烦,因为每次调用服务器端都要进行验证,所以设计了一个签名算法,官方的文档如下:

      

签名算法

云推送服务API使用的签名算法如下:

  • 获取请求的http method
  • 获取请求的url,包括host和sheme,但不包括query_string的部分
  • 将所有参数(包括GET或POST的参数,但不包含签名字段)格式化为“key=value”格式,如“k1=v1”、“k2=v2”、“k3=v3”;
  • 将格式化好的参数键值对以字典序升序排列后,拼接在一起,如“k1=v1k2=v2k3=v3”,并将http method和url按顺序拼接在这个字符串前面;
  • 在拼接好的字符串末尾追加上应用的secret_key,并进行urlencode形成base_string;
  • 上述字符串的MD5值即为签名的值:
sign=MD5(urlencode($http_method$url$k1=$v1$k2=$v2$k3=$v3$secret_key)); 
说明:
$secret_key:通过“开发者中心 -> 管理中心 -> 点击某应用 -> 应用信息详情页” 获得。

举例:

url [POST]: 

http://{domain}/rest/2.0/channel/channel?method=token&timestamp=1313293563&expires=1313293565&v=1

   

 

         从官方文档来看,有几点是很重要的

  1.  http method参数是必须的,从rest api中发现,目前也只支持get和post
  2. host和scheme参数也是必须的,官方文档中说明支持https和http两种
  3. 签名字段不参加签名字段的生成
  4. 其他所有的参数按照key=value的方式拼成一个字符串
  5. 字符串末尾加上sk的值
  6. 将前面的字符串使用urlencode进行编码
  7. 将urlencode编码后的字符串生成md5值

       这个里面其他的地方都是没什么的,关键是参数的顺序,我们知道,客户端给服务器端提交参数的时候是没有顺序的,当时我在实现的时候发现,有一些方法的签名是对的,有一些被服务器端当成错误的签名了,琢磨不透参数的顺序是怎么样的,最后反复研究官方文档发现,参数的顺序是按照参数的字母顺序排列的。发现了这个,其他的都很简单了,直接上代码。

 

         

package com.baidu.push.auth;

/**
 * AK和SK是应用访问资源或服务的唯一凭证。 查看AK和SK信息
 * @see <a href="http://developer.baidu.com/wiki/index.php?title=docs/cplat/push/guide">官方文档</a>
 * 
 * @author liyazhou@baidu.com
 *
 */
public class PushCredentials {

	private String accessKey;
	private String secretKey;

	public PushCredentials(String accessKey, String secretKey) {
		this.accessKey = accessKey;
		this.secretKey = secretKey;
	}

	public String getAccessKey() {
		return this.accessKey;
	}

	public String getSecretKey() {
		return this.secretKey;
	}
}

 PushCredentials这个里面是对ak和sk的一个简单封装,没有什么。

 

package com.baidu.push.auth;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.baidu.push.http.PushHttpRequest;
import com.baidu.push.reqeust.BaiduPushRequest;
import com.baidu.push.util.Constants;
import com.baidu.push.util.PushClientException;

/**
 * 生成签名算法
 * 
 * @see <a href="http://developer.baidu.com/wiki/index.php?title=docs/cplat/push/api">官方文档</a>
 * 
 * @author liyazhou@baidu.com
 *
 */
public class PushSigner {
	private static final Log log = LogFactory.getLog(PushSigner.class);
	
	private static String urlencode(String str) throws UnsupportedEncodingException {
		String rc = URLEncoder.encode(str, "utf-8");
		return rc.replace("*", "%2A");
	}
	
	public static void sign(BaiduPushRequest pushRequest,PushHttpRequest httpRequest, PushCredentials credentials) {
		StringBuilder signContents = new StringBuilder();
		// generate sign content
		if (null == pushRequest.getHttpMethod()) {
			throw new PushClientException("Sign failed! Param: httpMethod can not be empty!");
		}
		
		signContents.append(pushRequest.getHttpMethod().toString());
		if(pushRequest.isNeedSsl()){
			signContents.append(Constants.HTTPS);
		} else {
			signContents.append(Constants.HTTP);
		}
		signContents.append(Constants.PUSH_URL);
		
		if(pushRequest.getChannelId() == null){
			signContents.append(Constants.CHANNEL);
		} else {
			signContents.append(pushRequest.getChannelId());
		}
		Map<String,String> sinParameters = httpRequest.getParameters();
		for(Map.Entry<String, String> i : sinParameters.entrySet()) {
			signContents.append(i.getKey());
			signContents.append('=');
			signContents.append(i.getValue());
		}
		signContents.append(credentials.getSecretKey());
		log.info("signContents:"+signContents);
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.reset();
			//md.update( URLEncoder.encode(sb.toString(), "utf-8").getBytes() );
			md.update(urlencode(signContents.toString()).getBytes() );
			byte[] md5  = md.digest();
			
			signContents.setLength(0);
			for(byte b : md5) {
				signContents.append( String.format("%02x", b & 0xff));
			}
			
			httpRequest.addParameter("sign", signContents.toString());
		} catch (NoSuchAlgorithmException e) {
			log.error("error:"+e);
			throw new PushClientException("Sign failed! reason:"+e.getMessage());
		} catch (UnsupportedEncodingException e) {
			log.error("error:"+e);
			throw new PushClientException("Sign failed! reason:"+e.getMessage());
		}
	}
	
}

    

      PushSigner 这个类也很好理解,如果明白了签名算法,这个就是小case了,把这个留给广大同仁自己琢磨吧。

 

分享到:
评论
2 楼 asialee 2013-09-23  
sunsnow8 写道
您好,谢谢您的代码,不过com.baidu.push.http.PushHttpRequest;这个包在哪里?谢谢了,我想使用这个签名算法

代码在这里: https://github.com/twolfteam/baiduPush-java-sdk
1 楼 sunsnow8 2013-09-13  
您好,谢谢您的代码,不过com.baidu.push.http.PushHttpRequest;这个包在哪里?谢谢了,我想使用这个签名算法

相关推荐

    百度云推送 java端代码

    综上所述,实现百度云推送的Java服务器端代码,需要理解百度云推送的API接口,使用提供的SDK进行设备注册、消息发送、标签管理等操作,并处理回调和错误。同时,还需要关注安全性、性能和用户体验。通过这些方法,...

    安卓消息推送通知栏相关-Android百度云推送通过百度云推送的SDK和下载的demo实现一个简单的消息推送.rar

    总的来说,通过集成百度云推送SDK并参照示例项目,开发者可以轻松地在Android应用中实现消息推送功能,提高用户体验,增加应用的活跃度。但需要注意,随着Android系统的更新,推送通知的实现可能会有所变化,因此...

    百度云推送代码

    2. **集成SDK**:将百度云推送的SDK导入Java项目,根据官方文档配置依赖库。 3. **初始化**:在应用程序启动时初始化推送服务,传入APPID和密钥。 4. **注册设备**:当用户首次启动应用或安装新设备时,调用API...

    基于百度云推送的实例

    在Android端,你需要集成百度云推送SDK,设置必要的初始化参数,并实现接收和处理推送消息的接口。这通常涉及到在应用程序启动时进行初始化,以及创建BroadcastReceiver来接收推送通知。源代码中可能还包括了处理...

    阿里云推送 java服务器端sdk jar包

    阿里云推送Java服务器端SDK是开发者在构建基于Java的应用程序时,用于集成阿里云推送服务的重要工具。这个SDK使得开发者能够方便地将消息推送功能整合到自己的后台服务中,从而实现向Android、iOS以及Web等多平台...

    android百度云实现消息推送

    在Android开发中,为了实现实时的消息推送功能,开发者经常会选择使用第三方服务,其中百度云推送(Baidu Cloud Push)是一个常见的选择。本教程将详细讲解如何在Android应用中集成百度云推送,以实现高效、稳定的...

    c#实现推送通过的是百度云

    本项目以"C#实现推送通过的是百度云"为主题,这意味着我们将探讨如何利用C#编程语言与百度云推送服务进行集成,实现消息的发送和接收。 首先,我们要了解百度云推送(Baidu Cloud Push)是百度提供的一种云服务,它...

    百度云推送SDKbpush-nodejs.zip

    bpush-nodejs 是百度云推送 nodejs sdk,使用简单,部署方便,基于百度云推送 rest api 3.0开发。使用npm install bpush-nodejs --savevar bpush = require('bpush-nodejs'); ...说明SDK采用Promise方式进行回调,...

    Android推送 利用REST API实现从客户端推送(百度云推送)

    本文将深入探讨如何利用REST API实现从客户端进行Android推送,特别关注百度云推送这一服务。首先,我们需要了解REST(Representational State Transfer)架构风格,它是一种通过HTTP协议进行数据交互的方式,简洁且...

    Android应用源码基于百度云推送的IM项目.zip

    在本项目中,我们主要探讨的是一个基于Android平台的即时通讯(IM)应用程序,它利用了百度云推送服务来实现实时的消息传输。这个压缩包包含的“Android应用源码基于百度云推送的IM项目”提供了完整的源代码,让我们...

    阿里云邮件推送服务-SDK手册.pdf

    阿里云邮件推送服务-SDK手册是阿里云提供的一款邮件推送服务的SDK使用手册,该手册提供了详细的指导和示例代码,帮助开发者快速上手使用阿里云邮件推送服务。 Access Key的创建 在使用阿里云邮件推送服务之前,...

    百度云推送

    通过集成百度云推送的SDK,开发者可以实现向用户的移动设备发送各种类型的消息,如通知、自定义消息等,从而提高用户活跃度和应用黏性。 在Android平台上,"Baidu-Push-SDK-Android-L2-5.0.0.66"是百度云推送的一个...

    phonegap 百度云推送、扫描二维码、自动更新插件

    在PhoneGap中集成百度云推送,你需要先在百度开放平台上注册并获取APPID和密钥,然后将对应的SDK导入到项目中,配置相应的推送服务,并处理接收和显示推送消息的逻辑。此外,描述中提到的通知栏消息单击后自定义打开...

    yozo永中签名JavaSDK

    yozo永中签名JavaSDK

    友盟消息推送 Java服务端Push SDK

    消息推送(Push SDK) 友盟消息推送,帮助开发者建立于用户直接沟通的渠道。将APP的内 友盟推送PushSDK 友盟推送PushSDK 容更新或者活动通知主动推送给终端用户,让用户第一时间获取到相关信息,有效提升用户活跃度...

    baidu云存储java sdk源码阅读之安全

    【标题】:“baidu云存储java sdk源码阅读之安全” 在阅读Baidu云存储Java SDK的源码时,我们关注的重点是其如何确保数据的安全性。Baidu云存储(Baidu BOS)提供了一种高效、可靠的云存储服务,而它的Java SDK则...

    阿里云推送java服务器端的jar包

    阿里云推送服务是一款高效、稳定、可扩展的云端消息推送平台,它允许开发者向移动设备发送消息,以实现即时通信和应用更新提醒等功能。在Java服务器端,通过使用阿里云提供的SDK,我们可以轻松地集成推送服务到我们...

    个推java版sdk

    "个推Java版SDK"是专门为Java开发者设计的推送服务工具包,用于集成到各种Java应用程序中,实现高效、稳定的消息推送功能。个推作为国内知名的推送服务提供商,其SDK提供了丰富的功能,包括但不限于实时消息推送、...

    友盟消息推送Java springboot

    友盟消息推送服务作为一个广泛使用的第三方平台,为开发者提供了便捷的API和SDK,帮助他们实现高效、稳定的消息推送功能。本文将深入探讨如何在Java SpringBoot项目中集成友盟消息推送服务,并通过Redis缓存来管理推...

Global site tag (gtag.js) - Google Analytics