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;

运行结果,有图有真相

打完收工。

原文地址:https://www.cnblogs.com/xalion/p/9655774.html

时间: 2024-08-01 23:44:05

kbmmw 做REST 服务签名认证的一种方式的相关文章

XFire构建服务端Service的两种方式

1.原声构建:2.集成spring构建 http://blog.csdn.net/carefree31441/article/details/4000436XFire构建服务端Service的两种方式

Android: Android Studio签名打包的两种方式(zz)

注:给我们自己开发的app签名,就代表着我自己的版权,以后要进行升级,也必须要使用相同的签名才行.签名就代表着自己的身份(即keystore),多个app可以使用同一个签名. 如果不知道签名是啥意思,请自行百度哦.在eclipse中签名的方法是:选中工程,邮件选择"export-android-export android application", 1.方式1:通过Android Studio进行签名: 选中app这个module,选择菜单栏"Build-Generate

android studio学习---签名打包的两种方式

注:给我们自己开发的app签名,就代表着我自己的版权,以后要进行升级,也必须要使用相同的签名才行.签名就代表着自己的身份(即keystore),多个app可以使用同一个签名. 如果不知道签名是啥意思,请自行百度哦.在eclipse中签名的方法是:选中工程,邮件选择"export-android-export android application", 1.方式1:通过Android Studio进行签名: 选中app这个module,选择菜单栏"Build-Generate

android客户端与服务端交互的三种方式

android客户端向服务器通信一般有以下选择: 1.传统的java.net.HttpURLConnection类 2.apache的httpClient框架(已纳入android.jar中,可直接使用) 3.github上的开源框架async-http(基于httpClient) ---------------------------------------------------------------------------------- 下面分别记录这三种方式的使用, 传统方式: /**

登录认证的两种方式

一.手动输入验证码 def v_code(request): from PIL import Image,ImageDraw,ImageFont import random #定义一个生成随机颜色代码的内部函数,返回值对应RGB()里面的三个参数值 def get_color(): return random.randint(0,255),random.randint(0,255),random.randint(0,255) #生成一个图片对象 img_obj=Image.new( 'RGB',

SpringCloud服务消费有哪几种方式?

一.使用LoadBalancerClientLoadBalancerClient接口的命名中,可以看出这是一个负载均衡客户端的抽象定义,spring提供了一个实现org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient1.pom.xml<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-s

WCF服务使用(IIS+Http)和(Winform宿主+Tcp)两种方式进行发布

1.写在前面 刚接触WCF不久,有很多地方知其然不知其所以然.当我在[创建服务->发布服务->使用服务]这一过程出现过许多问题.如客户端找不到服务引用:客户端只在本机环境中才能访问服务,移植到其他机器上就不能访问服务(权限问题)等问题.所以写下这篇文章把我使用http和tcp这两方式部署服务所出现的问题以及解决方案记录下来,方便自己下次查看,也可以当作初学WCF的一个入门小示例吧. 2.建立一个WCF服务 首先要编写一个WCF服务,我在这里提供一个通过名字查询年龄的服务,代码如下: 服务契约:

RESTful接口签名认证实现机制

RESTful接口 互联网发展至今,催生出了很多丰富多彩的应用,极大地调动了人们对这些应用的使用热情.但同时也为互联网应用带来了严峻的考验.具体体现在以下几个方面: 1.     部署方式的改变:当用户量不多的情况下,可能只需部署一台服务器就可以解决问题,但是当很多用户的情况下,为抗住高并发访问,需要组成应用集群对外提供服务: 2.     应用构建的改变:很多应用采用了多种技术解决方案,不同编程语言(如C,Java,Python),所以很难采用传统应用构建模式将不同模块整合进来: 3.    

微信服务号认证流程

一.申请微信认证 1.申请微信认证入口. 1) “设置->账户信息->认证情况“点击“申请微信认证”进入. 2) “服务->服务中心“点击“微信认证”进入. 2.申请微信认证操作全攻略. 1) 签署<微信公众平台认证服务协议>,勾选同意,点击下一步. 2) 同意<公众号命名规则>,勾选同意,点击下一步. 3) 填写资料:根据账号类型选择企业或媒体(目前只支持这两种类型),并如实填写认证资料. 特别说明:企业对公银行帐户为必填项,在审核过程中第三方审核公司会向该帐户