下面的示例可作为api服务的参考,将(时间+信息+url+秘钥)进行哈希加密,附到header里面发送,可以保证信息不被篡改,同时服务端设置客户端和服务端时间偏差不能大于5分钟,5分钟内同一报文不能发送两次,否则都要返回错误,这样可以保证信息正确,即使被盗取,发送给服务端也不合法,但是不能发送私密信息
下面是python示例
[root@master ~]#cat a.py #!/usr/bin/env python #encoding=utf-8 import time import base64 import hashlib import httplib import uuid import hmac class SMSClient: def __init__(self, app_key, app_secret): self.__app_key, self.__app_secret = app_key, app_secret def send(self, receiver, sign, template_code, parameters=''): print receiver, sign, template_code, parameters self.__host = 'sms.market.alicloudapi.com' self.__str_uri = '/singleSendSms?ParamString=%s&RecNum=%s&SignName=%s&TemplateCode=%s' % (parameters, receiver, sign, template_code) print self.__str_uri self.build_headers() self.__connection = httplib.HTTPConnection(self.__host, 80) self.__connection.connect() self.__connection.request('GET', self.__str_uri, headers=self.__headers) response = self.__connection.getresponse() print response.status, response.getheaders(), response.read() def build_headers(self): headers = dict() headers['X-Ca-Key'] = self.__app_key headers['X-Ca-Nonce'] = str(uuid.uuid4()) headers['X-Ca-Timestamp'] = str(int(time.time() * 1000)) headers['X-Ca-Signature-Headers'] = 'X-Ca-Key,X-Ca-Nonce,X-Ca-Timestamp' str_header = '\n'.join('%s:%s' % (k, headers[k]) for k in ['X-Ca-Key','X-Ca-Nonce','X-Ca-Timestamp']) str_to_sign = '%s\n\n\n\n\n%s\n%s' % ('GET', str_header, self.__str_uri) headers['X-Ca-Signature'] = self.__get_sign(str_to_sign, self.__app_secret) self.__headers = headers def __get_sign(self, source, secret): h = hmac.new(secret, source, hashlib.sha256) signature = base64.encodestring(h.digest()).strip() return signature cli = SMSClient(app_key="24544195", app_secret="52a73ee2d28571115a4dead5f25a264f") cli.send('15211112222', '名字','SMS_105630061', '{"no":"12345"}') [root@master ~]#python a.py 15211111111 名字 SMS_105630061 {"no":"12345"} /singleSendSms?ParamString={"no":"12345"}&RecNum=152111111111&SignName=名字&TemplateCode=SMS_105630061 200 [('content-length', '16'), ('access-control-allow-headers', 'X-Requested-With,X-Sequence,X-Ca-Key,\ X-Ca-Secret,X-Ca-Version,X-Ca-Timestamp,X-Ca-Nonce,X-Ca-API-Key,X-Ca-Stage,X-Ca-Client-DeviceId,\ X-Ca-Client-AppId,X-Ca-Signature,X-Ca-Signature-Headers,X-Ca-Signature-Method,X-Forwarded-For,X-Ca-Date,\ X-Ca-Request-Mode,Authorization,Content-Type,Accept,Accept-Ranges,Cache-Control,Range,Content-MD5'), \ ('access-control-max-age', '172800'), ('server', 'Tengine'), ('connection', 'keep-alive'), \ ('date', 'Sun, 21 Jan 2018 16:18:17 GMT'), ('access-control-allow-origin', '*'), ('access-control-allow-methods',\ 'GET,POST,PUT,DELETE,HEAD,OPTIONS,PATCH'), ('content-type', 'text/plain;charset=ISO-8859-1'), ('x-ca-request-id', \ '350CE561-6073-4FBE-AA46-99E373BA533C')] {"success":true}
下面是shell示例
[root@master ~]#cat a.sh #!/usr/bin/env bash RECEIVER=15211111111 #接收方手机号 SIGN="名字" #签名 TEMP_CODE="SMS_105630061" #短信模板 PARAMS="{\"no\":\"123456\"}" #模板参数(json格式) K="24544195" #AppKey,从管理控制台获取,下同 S="52a73ee2d28571115a4dead5f25a264f" #AppSecret NL=" " [ "x`uname`" = "xDarwin" ] && { NONCE="`uuidgen`" TIMESTAMP="`date +%s`500" } || { NONCE="`uuid`" TIMESTAMP="`date +%s%3N`" } STR_HEADER="X-Ca-Key:$K${NL}X-Ca-Nonce:$NONCE${NL}X-Ca-Timestamp:$TIMESTAMP" STR_URI="/singleSendSms?ParamString=$PARAMS&RecNum=$RECEIVER&SignName=$SIGN&TemplateCode=$TEMP_CODE" STR_TO_SIGN="GET${NL}${NL}${NL}${NL}${NL}$STR_HEADER${NL}$STR_URI" SIGN="`/bin/echo -n "$STR_TO_SIGN" | openssl dgst -sha256 -hmac "$S" | sed 's/.* //g' | xxd -r -p | base64`" STR_URI="`echo "$STR_URI" | sed 's#{#\\\\{#g;s#}#\\\\}#g'`" curl -v -H 'Accept:' \ -H "X-Ca-Key: $K" \ -H "X-Ca-Nonce: $NONCE" \ -H "X-Ca-Timestamp: $TIMESTAMP" \ -H "X-Ca-Signature-Headers: X-Ca-Key,X-Ca-Nonce,X-Ca-Timestamp" \ -H "X-Ca-Signature: $SIGN" \ "http://sms.market.alicloudapi.com$STR_URI" [root@master ~]#bash a.sh * About to connect() to sms.market.alicloudapi.com port 80 (#0) * Trying 112.124.219.217... connected * Connected to sms.market.alicloudapi.com (112.124.219.217) port 80 (#0) > GET /singleSendSms?ParamString={"no":"123456"}&RecNum=15211111111&SignName=名字&TemplateCode=SMS_105630061 HTTP/1.1 > User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3 libidn/1.18 libssh2/1.4.2 > Host: sms.market.alicloudapi.com > X-Ca-Key: 24548195 > X-Ca-Nonce: 930821ea-fec5-11e7-9997-00505624745f > X-Ca-Timestamp: 1516551018689 > X-Ca-Signature-Headers: X-Ca-Key,X-Ca-Nonce,X-Ca-Timestamp > X-Ca-Signature: 5mGyVEdPX5efeOHQRRNo9jPbDF1Knsh1Mf1JqnU8TmQ= > < HTTP/1.1 200 OK < Server: Tengine < Date: Sun, 21 Jan 2018 16:23:21 GMT < Content-Type: text/plain;charset=ISO-8859-1 < Content-Length: 16 < Connection: keep-alive < Access-Control-Allow-Origin: * < Access-Control-Allow-Methods: GET,POST,PUT,DELETE,HEAD,OPTIONS,PATCH < Access-Control-Allow-Headers: X-Requested-With,X-Sequence,X-Ca-Key,X-Ca-Secret,X-Ca-Version,X-Ca-Timestamp,X-Ca-Nonce,\ X-Ca-API-Key,X-Ca-Stage,X-Ca-Client-DeviceId,X-Ca-Client-AppId,X-Ca-Signature,X-Ca-Signature-Headers,X-Ca-Signature-Method,\ X-Forwarded-For,X-Ca-Date,X-Ca-Request-Mode,Authorization,Content-Type,Accept,Accept-Ranges,Cache-Control,Range,Content-MD5 < Access-Control-Max-Age: 172800 < X-Ca-Request-Id: 47E5BA80-76D8-44DF-A0E6-C4312DED1826 < * Connection #0 to host sms.market.alicloudapi.com left intact * Closing connection #0 {"success":true}
HMAC介绍:
Hash-based message authentication code,利用哈希算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。
a specific construction for calculating a message authentication code (MAC) involving a cryptographic hash function in combination with a secret cryptographic key. As with any MAC, it may be used to simultaneously verify both the data integrity and the authenticity of a message.【主要是为了能让人对对方身份正确性和消息有效性进行验证,与消息摘要的最大不同,就是有签名密钥!】
应用:
HMAC的一个典型应用是用在“挑战/响应”(Challenge/Response)身份认证中
1. 客户端向服务器发出一个验证请求
2. 服务器接到此请求后生成一个随机数并通过网络传输给客户端(此为挑战)
3. 客户端将收到的随机数提供给ePass,由ePass使用该随机数与存储在ePass中的密钥进行HMAC-MD5运算并得到一个结果作为认证证据传给服务器(此为响应)。
4. 与此同时,服务器也使用该随机数与存储在服务器数据库中的该客户密钥进行HMAC-MD5运算,如果服务器的运算结果与客户端传回的响应结果相同,则认为客户端是一个合法用户
安全性:
HMAC算法更象是一种加密算法,它引入了密钥,其安全性已经不完全依赖于所使用的HASH算法
1. 使用的密钥是双方事先约定的,第三方不可能知道。能够得到的信息只有作为“挑战”的随机数和作为“响应”的HMAC结果,无法根据这两个数据推算出密钥。由于不知道密钥,所以无法仿造出一致的响应。
2. HMAC与一般的加密重要的区别在于它具有“瞬时”性,即认证只在当时有效
–
参考文档:https://yq.aliyun.com/articles/59928
–
–
–
评论前必须登录!
注册