• 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;

    运行结果,有图有真相

     

    打完收工。

  • 相关阅读:
    学习进度第三周
    四则运算3
    学习进度第二周
    单元测试
    四则运算2
    学习进度第一周
    四则运算1
    构建之法阅读笔记01
    linux: 讨论一下网络字节序--------大端与小端的差别
    linux编程:线程条件同步
  • 原文地址:https://www.cnblogs.com/xalion/p/9655774.html
Copyright © 2020-2023  润新知