http json tokensql
https使用證書來保證連接的安全,是目前最爲流行的作法。json
另外一種保證HTTP 函數的安全,就是http json token,只有TOKEN驗證經過,才能調用方法(通常指經過HTTP GET/POST調用的REST API)。安全
1)客戶端調用REST API的時候,要增長TOKEN參數及值函數
演示使用HS256,只有公鑰,沒有私鑰 url
procedure TForm1.Button5Click(Sender: TObject); //HTTP TOKEN begin const secret: string = 'ynMiddleWare(cross)'; //公鑰 var LToken: TJWT := TJWT.Create; LToken.Claims.Subject := secret; //主題 LToken.Claims.IssuedAt := Now; //簽發時間 LToken.Claims.Expiration := Now + 1; //超時 LToken.Claims.Issuer := secret; //簽發人 var LAlg: TJOSEAlgorithmId := TJOSEAlgorithmId.HS256; //hs256 var s: string := TJOSE.SerializeCompact(secret, LAlg, LToken); var url: string := 'http://192.168.1.5:1122/restquerytoken?accountno=1&token=' + s + '&sql=' + TNetEncoding.URL.Encode('select * from tunit'); s := IdHTTP1.Get(url); Memo1.Lines.Add(s); LToken.Free; end;
2)服務端處理rest
服務端驗證TOKEN的時候,主題、超時、簽發人。。。這些都是驗證可選項,最簡驗證:能夠只驗證密鑰。code
固然,驗證的項越多,越安全。驗證TOKEN不經過,不會執行函數的。orm
function VerifyToken(const request: string): string; begin const secret: string = 'ynMiddleWare(cross)'; //公鑰 var LToken: TJWT := TJOSE.Verify(secret, ParamValue(request, 'token')); if LToken.Verified then begin //主題、超時。。。等項,都是可選驗證項,驗證項越多,越安全 // if LToken.Claims.Subject <> '主題' then //主題 // begin // Result := '{"return":"false","error":"Subject error"}'; // exit; // end; // if LToken.Claims.Expiration < Now then //超時 // begin // Result := '{"return":"false","error":"Expiration time passed"}'; // Exit; // end; // if LToken.Claims.Issuer <> '簽發人' then //簽發人 // begin // Result := '{"return":"false","error":"Issuer error"}'; // Exit; // end; Result := '{"return":"true"}'; end else Result := '{"return":"false","error":"Verify error"}'; LToken.Free; end;
FHttpServer.Get('/restquerytoken', procedure(ARequest: ICrossHttpRequest; AResponse: ICrossHttpResponse) begin var s: string := VerifyToken(ARequest.RawPathAndParams); //驗證token if sametext('{"return":"true"}', s) then //驗證經過 begin var Pool: TUnidacPool := GetDBPool(ParamValue(ARequest.RawPathAndParams, 'accountno')); var dm: TUnidac := Pool.lock; AResponse.send(dm.RestQuery(ARequest.RawPathAndParams)); Pool.unlock(dm); end else AResponse.send(s); //返回錯誤信息 end);