阿里云新版人脸识别基于JAVA签名校验使用示例教程-阿里云开发者社区

开发者社区> Java技术进阶> 正文
登录阅读全文

阿里云新版人脸识别基于JAVA签名校验使用示例教程

简介: 阿里云会对每个访问的请求进行身份验证,所以无论使用 HTTP 还是 HTTPS 协议提交请求,都需要在请求中包含签名(Signature)信息。通过使用 Access Key ID 和 Access Key Secret 进行对称加密的方法来验证请求的发送者身份。

概述

阿里云会对每个访问的请求进行身份验证,所以无论使用 HTTP 还是 HTTPS 协议提交请求,都需要在请求中包含签名(Signature)信息。通过使用 Access Key ID 和 Access Key Secret 进行对称加密的方法来验证请求的发送者身份。阿里云提供了多种语言的 SDK 及第三方 SDK,可以免去您对签名算法进行编码的麻烦。您可以从这里了解更多阿里云 SDK 的信息,前面系列博客也结合各种语言的SDK进行了实现。本文以DetectFace API为示例,演示实际基于签名校验的实现。

操作步骤

1、pom.xml

   <dependencies>
        <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.4</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/log4j/log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.google.collections/google-collections -->
        <dependency>
            <groupId>com.google.collections</groupId>
            <artifactId>google-collections</artifactId>
            <version>1.0-rc2</version>
        </dependency>
    </dependencies>

2、工具类:UrlUtil

import java.net.URLEncoder;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
public class UrlUtil {
    private static Logger logger = Logger.getLogger(UrlUtil.class);
    private final static String CHARSET_UTF8 = "utf8";
    /**
     *
     * @param url
     * @return
     */
    public static String urlEncode(String url) {
        if (!StringUtils.isEmpty(url)) {
            try {
                url = URLEncoder.encode(url, "UTF-8");
            } catch (Exception e) {
                logger.warn("Url encode error:" + e.getMessage());
            }
        }
        return url;
    }
    public static String generateQueryString(Map<String, String> params, boolean isEncodeKV) {
        StringBuilder canonicalizedQueryString = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (isEncodeKV)
                canonicalizedQueryString.append(percentEncode(entry.getKey())).append("=")
                        .append(percentEncode(entry.getValue())).append("&");
            else
                canonicalizedQueryString.append(entry.getKey()).append("=")
                        .append(entry.getValue()).append("&");
        }
        if (canonicalizedQueryString.length() > 1) {
            canonicalizedQueryString.setLength(canonicalizedQueryString.length() - 1);
        }
        return canonicalizedQueryString.toString();
    }
    public static String percentEncode(String value) {
        try {
            // 使用URLEncoder.encode编码后,将"+","*","%7E"做替换即满足 API规定的编码规范
            return value == null ? null : URLEncoder.encode(value, CHARSET_UTF8)
                    .replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
        } catch (Exception e) {
            //不可能发生的异常
        }
        return "";
    }
}

3、工具类:SignatureUtils

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Map;
import java.util.TreeMap;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
public class SignatureUtils {
    private final static String CHARSET_UTF8 = "utf8";
    private final static String ALGORITHM = "UTF-8";
    private final static String SEPARATOR = "&";
    public static Map<String, String> splitQueryString(String url)
            throws URISyntaxException, UnsupportedEncodingException {
        URI uri = new URI(url);
        String query = uri.getQuery();
        final String[] pairs = query.split("&");
        TreeMap<String, String> queryMap = new TreeMap<String, String>();
        for (String pair : pairs) {
            final int idx = pair.indexOf("=");
            final String key = idx > 0 ? pair.substring(0, idx) : pair;
            if (!queryMap.containsKey(key)) {
                queryMap.put(key, URLDecoder.decode(pair.substring(idx + 1), CHARSET_UTF8));
            }
        }
        return queryMap;
    }
    public static String generate(String method, Map<String, String> parameter,
                                  String accessKeySecret) throws Exception {
        String signString = generateSignString(method, parameter);
        System.out.println("signString---"+signString);
        byte[] signBytes = hmacSHA1Signature(accessKeySecret + "&", signString);
        String signature = newStringByBase64(signBytes);
        System.out.println("signature---"+signature);
        if ("POST".equals(method))
            return signature;
        return URLEncoder.encode(signature, "UTF-8");
    }
    public static String generateSignString(String httpMethod, Map<String, String> parameter)
            throws IOException {
        TreeMap<String, String> sortParameter = new TreeMap<String, String>();
        sortParameter.putAll(parameter);
        String canonicalizedQueryString = UrlUtil.generateQueryString(sortParameter, true);
        if (null == httpMethod) {
            throw new RuntimeException("httpMethod can not be empty");
        }
        StringBuilder stringToSign = new StringBuilder();
        stringToSign.append(httpMethod).append(SEPARATOR);
        stringToSign.append(percentEncode("/")).append(SEPARATOR);
        stringToSign.append(percentEncode(canonicalizedQueryString));
        return stringToSign.toString();
    }
    public static String percentEncode(String value) {
        try {
            return value == null ? null : URLEncoder.encode(value, CHARSET_UTF8)
                    .replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
        } catch (Exception e) {
        }
        return "";
    }
    public static byte[] hmacSHA1Signature(String secret, String baseString)
            throws Exception {
        if (StringUtils.isEmpty(secret)) {
            throw new IOException("secret can not be empty");
        }
        if (StringUtils.isEmpty(baseString)) {
            return null;
        }
        Mac mac = Mac.getInstance("HmacSHA1");
        SecretKeySpec keySpec = new SecretKeySpec(secret.getBytes(CHARSET_UTF8), ALGORITHM);
        mac.init(keySpec);
        return mac.doFinal(baseString.getBytes(CHARSET_UTF8));
    }
    public static String newStringByBase64(byte[] bytes)
            throws UnsupportedEncodingException {
        if (bytes == null || bytes.length == 0) {
            return null;
        }
        return new String(Base64.encodeBase64(bytes, false), CHARSET_UTF8);
    }
    public static void main(String[] args) {
        String str = "GET&%2F&AccessKeyId%3DCd***eHJuMOrT%26Action%3DDescribeInstances%26Format%3DJSON%26RegionId%3Dcn-hangzhou%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3D9fdf288**36082ebef%26SignatureVersion%3D1.0%26Timestamp%3D2015-12-21T09%253A05%253A44Z%26Version%3D2014-05-26";
        byte[] signBytes;
        try {
            signBytes = SignatureUtils.hmacSHA1Signature("byc****6HQmH" + "&", str.toString());
            String signature = SignatureUtils.newStringByBase64(signBytes);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

4、Main方法

import com.google.common.collect.Maps;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.net.URI;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.SimpleTimeZone;
import java.util.UUID;

public class Demo1 {
    private static String getQueryUrl(Map<String, String> param, String accessKeyId, String secret) throws Exception {
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        simpleDateFormat.setTimeZone(new SimpleTimeZone(0, "GMT"));
        String timestamp = simpleDateFormat.format(date);
        Map<String, String> publicParam = Maps.newHashMap();

        publicParam.put("AccessKeyId", accessKeyId);
        publicParam.put("Format", "json");
        publicParam.put("SignatureMethod", "Hmac-SHA1");
        publicParam.put("SignatureNonce", UUID.randomUUID().toString());
        publicParam.put("SignatureVersion", "1.0");
        publicParam.put("Timestamp", timestamp);
        publicParam.put("Version", "2018-12-03");
        publicParam.put("RegionId", "cn-shanghai");

        if (param != null) {
            for (Map.Entry<String, String> entry : param.entrySet()) {
                publicParam.put(entry.getKey(), entry.getValue());
            }
        }

        String s = SignatureUtils.generateSignString("POST", publicParam);
        byte[] signBytes;
        signBytes = SignatureUtils.hmacSHA1Signature(secret + "&", s);
        String signature = SignatureUtils.newStringByBase64(signBytes);

        publicParam.put("Signature", signature);

        String url = "http://face.cn-shanghai.aliyuncs.com/?";
        //对参数进行url编码
        for (Map.Entry<String, String> entry : publicParam.entrySet()) {
            publicParam.put(entry.getKey(), URLEncoder.encode(entry.getValue().toString(), "UTF-8"));
        }
        //拼接请求url
        for (Map.Entry<String, String> entry : publicParam.entrySet()) {
            url = url + entry + "&";
        }
        //去掉最后一个&
        url = url.substring(0, url.length() - 1);
        return url;
    }

    public static void main(String[] args) {
        try {
            Map<String, String> map = Maps.newHashMap();
            map.put("Action", "DetectFace");
            String imageUrl_1 = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1559655604341&di=3d6995f6dee1c4795d1827e754a00452&imgtype=0&src=http%3A%2F%2Fimg0.ph.126.net%2F90u9atgu46nnziAm1NMAGw%3D%3D%2F6631853916514183512.jpg";
            map.put("ImageUrl",imageUrl_1);

            // access_key_id, access_key_secret  获取参考链接:https://yq.aliyun.com/articles/693979?spm=a2c4e.11155435.0.0.319326a2bKJ90g
            String accessKeyId = "*******";
            String secret = "*******";
            String url = getQueryUrl(map, accessKeyId, secret);

            // 使用生成的 URL 创建POST请求
            URIBuilder builder = new URIBuilder(url);
            URI uri = builder.build();
            HttpPost request = new HttpPost(uri);
            HttpClient httpclient = HttpClients.createDefault();

            HttpResponse response = httpclient.execute(request);
            HttpEntity entity = response.getEntity();

            if (entity != null)
            {
                System.out.println(EntityUtils.toString(entity));
            }
        }
        catch (Exception e)
        {
            System.out.println(e.getMessage());
        }
    }
}

5、运行结果


{"Data":{"landmark":[799.2508544921875,1096.208740234375,1240.654296875,1094.9720458984375,1017.4330444335938,998.57861328125,1019.7756958007812,1073.234375,856.2061767578125,1035.13671875,933.8515625,1003.8469848632812,1100.0830078125,1011.6668701171875,1179.436767578125,1038.3056640625,872.8338623046875,1087.581298828125,945.71942138671875,1074.416015625,1093.3974609375,1081.538818359375,1166.590576171875,1092.97607421875,1493.1463623046875,1106.8787841796875,1803.4925537109375,1122.54248046875,1661.3282470703125,1008.6871948242188,1651.0706787109375,1079.126953125,1537.4063720703125,1056.8326416015625,1597.4547119140625,1028.1773681640625,1726.907470703125,1018.4874267578125,1778.471435546875,1060.5947265625,1546.176025390625,1099.3516845703125,1597.8970947265625,1085.4248046875,1704.5565185546875,1081.686279296875,1754.29541015625,1101.360595703125,950.329833984375,1237.64794921875,1183.385009765625,1267.03759765625,977.181396484375,1217.33203125,1007.8623046875,1203.468505859375,1040.79296875,1196.4024658203125,1074.479736328125,1197.28076171875,1107.569091796875,1203.653076171875,1138.1513671875,1217.7967529296875,1163.763427734375,1239.65087890625,972.8101806640625,1259.625244140625,999.7427978515625,1275.834716796875,1029.82177734375,1285.0888671875,1060.949951171875,1289.74853515625,1092.414306640625,1290.66357421875,1123.592041015625,1286.35107421875,1154.080322265625,1278.5302734375,1505.3389892578125,1268.0709228515625,1708.0179443359375,1249.576416015625,1518.981201171875,1239.8076171875,1538.6033935546875,1215.315185546875,1567.039306640625,1202.20703125,1598.1136474609375,1198.019775390625,1629.2843017578125,1201.669677734375,1659.324462890625,1210.7451171875,1686.067138671875,1227.1563720703125,1530.2646484375,1279.018310546875,1556.6688232421875,1285.6533203125,1583.6409912109375,1289.33984375,1610.8587646484375,1289.97509765625,1638.017578125,1288.05908203125,1664.3843994140625,1281.280517578125,1688.3682861328125,1268.41259765625,1356.669921875,1282.080322265625,1408.8363037109375,1560.64453125,1382.7197265625,1421.0,1381.5010986328125,1632.008056640625,1219.308349609375,1626.333251953125,1504.8509521484375,1610.831787109375,1130.4825439453125,1834.1395263671875,1509.7669677734375,1838.226318359375,1168.39501953125,1840.3800048828125,1477.0972900390625,1842.334228515625,1356.515380859375,1776.99951171875,1318.5791015625,1763.8675537109375,1391.8681640625,1763.096435546875,1223.385498046875,1796.4013671875,1458.71044921875,1788.520751953125,1175.30078125,1811.2015380859375,1270.33349609375,1778.24560546875,1426.817626953125,1771.79443359375,1487.899169921875,1809.6094970703125,1339.509521484375,1975.9508056640625,1215.365234375,1935.4556884765625,1444.841064453125,1933.088623046875,1168.38525390625,1888.6160888671875,1273.85400390625,1966.6778564453125,1396.037353515625,1963.970703125,1483.1046142578125,1889.708984375,1350.7132568359375,1842.592041015625,1342.6649169921875,1877.176025390625,1259.4251708984375,1840.41455078125,1253.5074462890625,1868.7591552734375,1413.9844970703125,1838.3511962890625,1413.215087890625,1872.574462890625,1213.9150390625,1836.5245361328125,1210.5072021484375,1855.8992919921875,1305.033935546875,1843.0133056640625,1297.79638671875,1876.015380859375,1382.399658203125,1841.2255859375,1378.171142578125,1878.257080078125,1445.6971435546875,1837.94091796875,1446.6396484375,1860.6153564453125,622.818603515625,1224.1640625,1785.5914306640625,1214.9752197265625,1357.4207763671875,2194.99365234375,768.70306396484375,1845.98193359375,1715.2325439453125,1736.135498046875,668.5491943359375,1537.0185546875,1775.165771484375,1473.250732421875,1036.9564208984375,2098.42333984375,1579.2042236328125,2001.826416015625],"pose":[10.426637649536133,-4.4992427825927734,-0.58456879854202271],"face_prob":[1.0],"request_id":"B95412C6-858B-47D4-B3A0-DBE0BA6188D9","errno":0,"face_num":1,"iris":[1071.598876953125,1235.034912109375,51.706081390380859,1573.8760986328125,1241.315673828125,51.706081390380859],"landmark_num":105,"face_rect":[679,539,1172,1664]},"RequestId":"B95412C6-858B-47D4-B3A0-DBE0BA6188D9","Success":true}

参考链接

签名算法参考

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享: