# 3.3 应用请求数据签名生成方法

第三方应用访问勤策服务接口时需要对请求数据做签名处理

# 3.3.1 服务端接口数据签名生成方法

第三方应用访问勤策服务接口时需要对请求数据做签名处理,签名信息包含(access_token-服务商授权码, timestamp-访问时间戳, nonce-随机字符串, echoStr-请求数据体)。
echoStr是接口定义中的请求示例,为JSON格式数据,如获取用户可用积分接口中echoStr示例

{"user_id": "7951571222327321975","user_type":"1"}

签名方法,根据签名数据值自然顺序排序后拼接成一个字符串,然后获取SHA-1签名。示例如下:

import java.security.MessageDigest;
import java.util.Arrays;

public class OAuth2Utils
{
	/**
	 * 根据数据生成签名信息(1.根据数据排序 2.排序后拼接成字符串生成SHA-1签名信息)
	 * @param accessToken 服务商授权Token
	 * @param timeStamp 时间戳
	 * @param nonce 随机字符串
	 * @param echoStr 请求数据体
	 * @return 签名信息
	 * @throws Exception
	 */
	public static String makeSignature(String accessToken, long timeStamp, String nonce, String echoStr) throws AesException
	{
		try {
			String[] array = new String[] { accessToken, String.valueOf(timeStamp), nonce, echoStr };
			StringBuffer sb = new StringBuffer();
			// 字符串排序
			Arrays.sort(array);
			for (int i = 0; i < 4; i++) {
				sb.append(array[i]);
			}
			String str = sb.toString();
			// SHA1签名生成
			MessageDigest md = MessageDigest.getInstance("SHA-1");
			md.update(str.getBytes());
			byte[] digest = md.digest();

			StringBuffer hexstr = new StringBuffer();
			String shaHex = "";
			for (int i = 0; i < digest.length; i++)
			{
				shaHex = Integer.toHexString(digest[i] & 0xFF);
				if (shaHex.length() < 2) {
					hexstr.append(0);
				}
				hexstr.append(shaHex);
			}
			return hexstr.toString();
		}
		catch (Exception e)
		{
			throw new Exception(e.getMessage());
		}
	}

}

# 3.3.2 JS-SDK 数据签名生成方法

第三方应用访问勤策客户端提供的JS-SDK接口时需要生成签名信息,签名信息需要jsapi_ticket、noncestr、timestamp、url信息
注意:请求的URL中需要将URL中'?'以及后面的参数和'#'以及后面的锚点相关部分去除。示例如下:


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.security.MessageDigest;

public class OAuth2JSSDKUtils
{
    private static final Logger LOGGER = LoggerFactory.getLogger(OAuth2JSSDKUtils.class);

    /**
     * 生成JS-SDK签名
     * @param str 签名字符串格式示例:
     *            jsapi_ticket=2020060316180943480984829434T-bba510f4f4634f8881e10caaa01212ef&noncestr=su9d51qf80sz2dxf&timestamp=1591165742&url=https://api.waiqin365.com/home.html
     *  注意:请求的URL中需要将URL中'?'以及后面的参数和'#'以及后面的锚点相关部分去除
     */
    private static String getSHA1(String str) throws Exception
    {
        try
        {

            LOGGER.info("oAuth2准备加密字符串:" + str);
            // SHA1签名生成
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            md.update(str.getBytes());
            byte[] digest = md.digest();

            StringBuffer hexstr = new StringBuffer();
            String shaHex = "";
            for(int i = 0; i < digest.length; i++)
            {
                shaHex = Integer.toHexString(digest[i] & 0xFF);
                if(shaHex.length() < 2)
                {
                    hexstr.append(0);
                }
                hexstr.append(shaHex);
            }
            LOGGER.info("oAuth2加密字符串结果:" + hexstr.toString());
            return hexstr.toString();
        }
        catch(Exception e)
        {
            LOGGER.warn("获取SHA-1加密字符串失败", e);
            throw e;
        }
    }
    /**
     * 获取签名信息
     * @param url 当前页面请求URL
     * @param jsapi_ticket ticket
     * @param noncestr 随机字符串
     * @param timestamp 时间戳
     * @return
     * @throws Exception
     */
    public static String getJsApiSignature(String url, String jsapi_ticket, String noncestr, String timestamp) throws Exception
    {
        if(url.indexOf("?") > -1)
        {
            url = url.substring(0, url.indexOf("?"));
        }
        if(url.indexOf("#") > -1)
        {
            url = url.substring(0, url.indexOf("#"));
        }

        StringBuffer sub = new StringBuffer();
        sub.append("jsapi_ticket=").append(jsapi_ticket);
        sub.append("&noncestr=").append(noncestr);
        sub.append("&timestamp=").append(timestamp);
        sub.append("&url=").append(url);

        return getSHA1(sub.toString());
    }

    public static void main(String[] args) throws Exception
    {
        String url = "https://api.waiqin365.com/open/?state=user&code=202101251552898873891063184228e069af6b94415ba56b47d0a2b71064&tenant_id=5528988738910631842&app_id=app1606897590447";
        String jsapi_ticket = "2021012515937937519423778872T-e79f5546d2654f05aad5b23e4b11270b";
        String noncestr = "4d8023becff64674858c4a7215f26c09";
        String timestamp = "1611544273";
        System.out.println(getJsApiSignature(url, jsapi_ticket, noncestr, timestamp));
    }
}