访问服务器安全规范

 一、安全规范

1:把当前时间戳加入请求GET参数,字段名为_time

2:把公钥加入请求GET参数,字段名为_ak 
3:把所有需要传递的参数的key按字母顺序进行排序(升序),空的参数不参与校验
4:排序所参数拼接成请求的字符串,如_ak=abcde&_time=2343243&key1=%E5%8F%82%E6%95%B02&key2=%E5%8F%82%E6%95%B01
5:把第三步所的字符串与_sk链接在一起作md5,生成的字符串加到_sign参数里,一并传到服务器

注意: 
1: 所有字符采用utf8编码
2: 参数必须先进行urlencode,再md5

3:只对GET内的参数做签名,签名参数附在url后面传递

package com.android.deskclock.utils;
import android.text.TextUtils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
/**
 * Tool to get signed request of letv server.
 *
 */
public class LeSignature {
    private static final String KEY_TIME ="_time";
    private static final String KEY_AK = "_ak";
    private static final String PARAMS_SEP = "&";
    private static final String REQUEST_CHARSET = "UTF-8";
    private static final char HEX_DIGITS[] = "0123456789abcdef".toCharArray();
    private static String toHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder(bytes.length * 2);
        for (byte b : bytes) {
            sb.append(HEX_DIGITS[(b & 0xf0) >>> 4]);
            sb.append(HEX_DIGITS[b & 0x0f]);
        }
        return sb.toString();
    }
    private static String join(Iterable<String> strings, String sep) {
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        for (String item : strings) {
            if (first) {
                first = false;
            } else {
                sb.append(sep);
            }
            sb.append(item);
        }
        return sb.toString();
    }
    /**
     * Get sign string of request params.
     * <p>
     * See <code>http://wiki.letv.cn/pages/viewpage.action?pageId=37325204</code>
     *
     * @param accessKey Access key of client.
     * @param secretKey Secret key of client.
     * @param params Params of request.
     * @param time Current timestamp.
     * @return Result of sign
     */
    public static String getSignature(String accessKey, String secretKey, Map<String, String> params, long time) {
        if (isEmpty(accessKey) || isEmpty(secretKey)) {
            throw new IllegalArgumentException("You MUST set access key and secret key for the request!");
        }
        SortedSet<String> set = new TreeSet<String>();
        try {
            set.add(KEY_TIME + "=" + URLEncoder.encode(String.valueOf(time), REQUEST_CHARSET));
            set.add(KEY_AK + "=" + URLEncoder.encode(accessKey, REQUEST_CHARSET));
            if (params != null && params.size() > 0) {
                for (String param : params.keySet()) {
                    String value = params.get(param);
                    if (!TextUtils.isEmpty(value)) {
                        set.add(param + "=" + URLEncoder.encode(value, REQUEST_CHARSET));
                    }
                }
            }
            String paramsString = join(set, PARAMS_SEP);
            String str2Sign = paramsString + secretKey;
            MessageDigest digest = MessageDigest.getInstance("MD5");
            digest.update(str2Sign.getBytes(REQUEST_CHARSET));
            return toHexString(digest.digest());
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }
    /**
     * Get sign string of request params and body.
     * <p>
     * See <code>http://wiki.letv.cn/pages/viewpage.action?pageId=37323874</code>
     *
     * @param accessKey Access key of client.
     * @param method Method of request, liking POST, GET etc.
     * @param path Path of request, for example "/api/v1/message".
     * @param body Body of request.
     * @param time Current timestamp.
     * @param params Params of request.
     * @return Result of sign
     */
    public static String getSignature(String accessKey, String method, String path, byte[] body,
                                      long time, Map<String, String> params) {
        if (isEmpty(accessKey)) {
            throw new IllegalArgumentException("You MUST set access key for request!");
        }
        try {
            String bodyMD5 = "";
            if (body != null && body.length != 0) {
                MessageDigest digest;
                digest = MessageDigest.getInstance("MD5");
                digest.update(body);
                bodyMD5 = toHexString(digest.digest());
            }
            String paramString = "";
            if (params != null && params.size() > 0) {
                SortedSet<String> set = new TreeSet<String>();
                for (String param : params.keySet()) {
                    String value = params.get(param);
                    if (!TextUtils.isEmpty(value)) {
                        set.add(param + "=" + value);
                    }
                }
                paramString = join(set, PARAMS_SEP);
            }
            SimpleDateFormat fm=new SimpleDateFormat("EEE, d MMM yyyy hh:mm:ss z");
            String date = fm.format(new Date(time));
            String stringToSign = method.toUpperCase() + "\n" + path + "\n" + bodyMD5 + "\n" + date + "\n" + paramString;
            SecretKeySpec signingKey = new SecretKeySpec(accessKey.getBytes(), "HmacSHA1");
            Mac mac = Mac.getInstance("HmacSHA1");
            mac.init(signingKey);
            byte[] rawHmac = mac.doFinal(stringToSign.getBytes());
            return toHexString(rawHmac);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        return "";
    }
    private static boolean isEmpty(CharSequence str) {
        return (str == null || str.toString().trim().length() == 0);
    }
}

猜你喜欢

转载自my.oschina.net/u/3336230/blog/1600927