kbmmw 做REST 服务签名认证的一种方式
Posted xalion
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kbmmw 做REST 服务签名认证的一种方式相关的知识,希望对你有一定的参考价值。
一般对外提供提供REST 服务,由于信息安全的问题, 都要采用签名认证,今天简单说一下在KBMMW 中如何
实现简单的签名服务?
整个签名服务,模仿阿里大鱼的认证方式,大家可以根据实际情况自己修改。
没有太多的解释,直接上马
[kbmMW_Rest(‘method:get, path:getwithcheck‘)] [kbmMW_Method] function getwithcheck( [kbmMW_Rest(‘value: "$p1", required: true‘)] const p1:string; [kbmMW_Rest(‘value: "$p2", required: true‘)] const p2:string; [kbmMW_Rest(‘value: "$p3", required: true‘)] const p3:string; [kbmMW_Rest(‘value: "$AccessKeyId", required: true‘)] const AccessKeyId:string; [kbmMW_Rest(‘value: "$Timestamp", required: true‘)] const Timestamp:string; [kbmMW_Rest(‘value: "$Action", required: true‘)] const Action:string; [kbmMW_Rest(‘value: "$Signature", required: true‘)] const Signature:string):string; end; const AppSecret=‘sdjhidbTdlfdsj133edyeR‘; appkey=‘xaliontestok‘; function MakeSign(const AParams: TStringList; const AppSecret: string): string; implementation uses kbmMWExceptions, mainp; {$R *.dfm} function specialUrlEncode(const sStr:string):string; begin // URLEncode后再增加三种字符替换:加号(+)替换成 %20、星号(*)替换成 %2A、%7E 替换回波浪号(~) Result :=TNetEncoding.URL.EncodeForm(sStr); Result.Replace(‘+‘,‘%20‘).Replace(‘*‘,‘%2A‘).Replace(‘%7E‘,‘~‘); end; function MakeSign(const AParams: TStringList; const AppSecret: string): string; var I: Integer; sortedQueryString :string; stringToSign: string; sSign :string; outs: TStringList; pn,pv:string; skey:Tbytes; begin outs:= AParams; outs.UseLocale:=True; outs.Sort; // 参数拼接 sortedQueryString:= ‘‘; for I := 0 to outs.Count - 1 do begin pn:=specialUrlEncode(outs.Names[I]); pv:=specialUrlEncode(outs.Values[outs.Names[I]]); sortedQueryString:= sortedQueryString +pn + ‘=‘+ pv+‘&‘; end; setlength(sortedQueryString,length(sortedQueryString)-1); stringToSign :=‘GET&%2F&‘ + specialUrlEncode(sortedQueryString); skey:=THashSHA1.GetHMACAsBytes(Tencoding.UTF8.GetBytes(stringToSign), Tencoding.UTF8.GetBytes(AppSecret+‘&‘)); sSign := TBase64Encoding.Create.EncodeBytesToString(skey); Result :=specialUrlEncode(sSign); end; function TkbmMWCustomHTTPSmartService1.getwithcheck(const p1, p2, p3, AccessKeyId, Timestamp, Action, Signature: string): string; var inputp:Tstringlist; inputsign:string; begin inputp:=Tstringlist.Create; inputp.Values[‘P1‘]:=p1; inputp.Values[‘P2‘]:=p2; inputp.Values[‘P3‘]:=p3; inputp.Values[‘AccessKeyId‘]:=AccessKeyId; inputp.Values[‘Timestamp‘]:=Timestamp; inputp.Values[‘Action‘]:=Action; // inputp.Values[‘Signature‘]=Signature; inputsign:= MakeSign(inputp,AppSecret); if inputsign<>specialUrlEncode(Signature) then begin Result:=‘{result:{"ok":"error","value":"sign error"}}‘; exit; end; if appkey<>AccessKeyId then begin Result:=‘{result:{"ok":"error","value":"can not find appkey"}}‘; exit; end; Result:=‘{"result":{"ok":"ok","value":"‘+Action+‘"}}‘;; end;
客户端也很简单
function TForm1.SendSMS(const AppKey, AppSecret, ReceiveNumber, FreeSignName, TemplateCode, TemplateContent: string; var ResultMsg: string): Boolean; function specialUrlEncode(const sStr:string):string; begin // URLEncode后再增加三种字符替换:加号(+)替换成 %20、星号(*)替换成 %2A、%7E 替换回波浪号(~) Result :=TNetEncoding.URL.EncodeForm(sStr); Result.Replace(‘+‘,‘%20‘).Replace(‘*‘,‘%2A‘).Replace(‘%7E‘,‘~‘); end; function MakeSign(const AParams: TStringList; const AppSecret: string;var sortQueryStringTmp :String): string; var I: Integer; sortedQueryString :string; stringToSign: string; sSign :string; outs: TStringList; pn,pv:string; skey:Tbytes; begin outs:= AParams; outs.UseLocale:=True; outs.Sort; //SortString( AParams,outs); // 参数拼接 sortQueryStringTmp := ‘‘; for I := 0 to outs.Count - 1 do begin pn:=specialUrlEncode(outs.Names[I]); pv:=specialUrlEncode(outs.Values[outs.Names[I]]); sortQueryStringTmp := sortQueryStringTmp +pn + ‘=‘+ pv+‘&‘; end; setlength(sortQueryStringTmp,length(sortQueryStringTmp)-1); sortedQueryString:=sortQueryStringTmp; stringToSign :=‘GET&%2F&‘ + specialUrlEncode(sortedQueryString); skey:=THashSHA1.GetHMACAsBytes(Tencoding.UTF8.GetBytes(stringToSign), Tencoding.UTF8.GetBytes(AppSecret+‘&‘)); sSign := TBase64Encoding.Create.EncodeBytesToString(skey); Result :=specialUrlEncode(sSign); end; var HTTP: TNetHTTPClient; JO: TJSONObject; Params: TStringList; Response: string; code:TGUID; sortQueryStringTmp :string; signature :string; sURL :string; ResponseStr: TStringStream; begin Result := False; CreateGUID(code); HTTP := TNetHTTPClient.Create(nil); Params := TStringList.Create(); ResponseStr :=TStringStream.Create(‘‘, TEncoding.ASCII);//中文用UTF8 try //; // //请求参数中不允许出现以Signature为key的参数。参考代码如下``` //String accessKeyId = “testId”;String accessSecret = “testSecret”; //java.text.SimpleDateFormat df = new java.text.SimpleDateFormat(“yyyy-MM-dd’T’HH:mm:ss’Z’”); //df.setTimeZone(new java.util.SimpleTimeZone(0, “GMT”));// 这里一定要设置GMT时区 // //java.util.Map paras = new java.util.HashMap(); //// 1. 系统参数 //paras.put(“SignatureMethod”, “HMAC-SHA1”); //paras.put(“SignatureNonce”, java.util.UUID.randomUUID().toString()); //paras.put(“AccessKeyId”, accessKeyId); //paras.put(“SignatureVersion”, “1.0”); //paras.put(“Timestamp”, df.format(new java.util.Date())); //paras.put(“Format”, “XML”); // //// 2. 业务API参数 //paras.put(“Action”, “SendSms”); //paras.put(“Version”, “2017-05-25”); //paras.put(“RegionId”, “cn-hangzhou”); //paras.put(“PhoneNumbers”, “15300000001”); //paras.put(“SignName”, “阿里云短信测试专用”); //paras.put(“TemplateParam”, “{”customer”:”test”}”); //paras.put(“TemplateCode”, “SMS_71390007”); //paras.put(“OutId”, “123”); Params.Values[‘P2‘] := ‘HMAC-SHA1‘; Params.Values[‘P3‘] := GUIDToString(code); Params.Values[‘AccessKeyId‘] := AppKey; Params.Values[‘P1‘] := ‘1.0‘; // Params.Values[‘Timestamp‘] := FormatDateTime(‘yyyy-mm-dd hh:mm:ss‘, now - 1/3); Params.Values[‘Timestamp‘] := FormatDateTime(‘yyyy-MM-dd‘‘T‘‘HH:mm:ss‘‘Z‘‘‘, now-1/3); // Params.Values[‘Format‘] := ‘JSON‘; Params.Values[‘Action‘] := ‘SendSms‘; // Params.Values[‘Version‘] := ‘2017-05-25‘; // Params.Values[‘RegionId‘] := ‘cn-hangzhou‘; //Params.Values[‘PhoneNumbers‘] := ReceiveNumber; // Params.Values[‘SignName‘] := FreeSignName; // Params.Values[‘TemplateParam‘] := TemplateContent; // Params.Values[‘TemplateCode‘] := TemplateCode; signature:=MakeSign(Params,AppSecret,sortQueryStringTmp); sURL := ‘http://127.0.0.1/xalionrest/getwithcheck?signature=‘+signature+‘&‘+sortQueryStringTmp; Memo1.Lines.Text :=sURL; try resultmsg:=http.Get(sURL).ContentAsString ; Memo2.Lines.add( resultmsg); except on E: Exception do begin ResultMsg := E.Message; Exit; end; end; finally HTTP.Free; Params.Free; ResponseStr.Free; end; end;
运行结果,有图有真相
打完收工。
以上是关于kbmmw 做REST 服务签名认证的一种方式的主要内容,如果未能解决你的问题,请参考以下文章
REST easy with kbmMW #15 – Handling HTTP POST
REST easy with kbmMW #4 – Access management