如何寫出安全的API接口

通過園友們的討論,以及我自己查了些資料,然后對接口安全做一個相對完善的總結,承諾給大家寫個demo,今天一并放出。

對于安全也是相對的,下面我來根據安全級別分析

?

1.完全開放的接口

有沒有這樣的接口,誰都可以調用,誰都可以訪問,不受時間空間限制,只要能連上互聯網就能調用,毫無安全可言。

實話說,這樣的接口我們天天都在接觸,你查快遞,你查天氣預報,你查飛機,火車班次等,這些都是有公共的接口。

我把這稱之為裸奔時代。代碼如下:

/// <summary>
/// 接口對外公開
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("NoSecure")]
public HttpResponseMessage NoSecure(int age)
{
var result = new ResultModel<object>()
{
ReturnCode = 0,
Message = string.Empty,
Result = string.Empty
};

var dataResult = stulist.Where(T => T.Age == age).ToList();
result.Result = dataResult;

return GetHttpResponseMessage(result);
}

?

2.接口參數加密(基礎加密)

?你寫個接口,你只想讓特定的調用方使用,你把這些調用的人叫到一個小屋子,給他們宣布說我這里有個接口只打算給你們用,我給你們每人一把鑰匙,你們用的時候拿著這把鑰匙即可。

這把鑰匙就是我上文說到的參數加密規則,有了這個規則就能調用。

這有安全問題啊,這里面的某個成員如果哪個不小心丟了鑰匙或者被人竊取,掌握鑰匙的人是不是也可以來掉用接口了呢?而且他可以復制很多鑰匙給不明不白的人用。

相當于有人拿到了你的請求鏈接,如果業務沒有對鏈接唯一性做判斷(實際上業務邏輯通常不會把每次請求的加密簽名記錄下來,所以不會做唯一性判斷),就會被重復調用,有一定安全漏洞,怎么破?先看這個場景的代碼,然后繼續往下看!

?

/// <summary>
/// 接口加密
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("SecureBySign")]
public HttpResponseMessage SecureBySign([FromUri]int age, long _timestamp, string appKey, string _sign)
{
var result = new ResultModel<object>()
{
ReturnCode = 0,
Message = string.Empty,
Result = string.Empty
};

#region 校驗簽名是否合法
var param = new SortedDictionary<string, string>(new AsciiComparer());
param.Add("age", age.ToString());
param.Add("appKey", appKey);
param.Add("_timestamp", _timestamp.ToString());

string currentSign = SignHelper.GetSign(param, appKey);

if (_sign != currentSign)
{
result.ReturnCode = -2;
result.Message = "簽名不合法";
return GetHttpResponseMessage(result);
}
#endregion

var dataResult = stulist.Where(T => T.Age == age).ToList();
result.Result = dataResult;

return GetHttpResponseMessage(result);
}

3.接口參數加密+接口時效性驗證(一般達到這個級別已經非常安全了)

繼上一步,你發現有不明不白的人調用你的接口,你很不爽,隨即把真正需要調用接口的人又叫來,告訴他們每天給他們換一把鑰匙。和往常一樣,有個別伙伴的鑰匙被小偷偷走了,小偷煞費苦心,經過數天的踩點觀察,準備在一個月黑風高的夜晚動手。拿出鑰匙,搗鼓了半天也無法開啟你的神圣之門,因為小偷不知道你天天都在換新鑰匙。

小偷不服,經過一段時間琢磨,小偷發現了你們換鑰匙的規律。在一次獲得鑰匙之后,不加思索,當天就動手了,因為他知道他手里的鑰匙在第二天你更換鑰匙后就失效了。

結果,小偷如愿。怎么破?先看這個場景的代碼,然后繼續往下看!

/// <summary>
/// 接口加密并根據時間戳判斷有效性
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("SecureBySign/Expired")]
public HttpResponseMessage SecureBySign_Expired([FromUri]int age, long _timestamp, string appKey, string _sign)
{
var result = new ResultModel<object>()
{
ReturnCode = 0,
Message = string.Empty,
Result = string.Empty
};

#region 判斷請求是否過期---假設過期時間是20秒
DateTime requestTime = GetDateTimeByTicks(_timestamp);

if (requestTime.AddSeconds(20) < DateTime.Now)
{
result.ReturnCode = -1;
result.Message = "接口過期";
return GetHttpResponseMessage(result);
}
#endregion

#region 校驗簽名是否合法
var param = new SortedDictionary<string, string>(new AsciiComparer());
param.Add("age", age.ToString());
param.Add("appKey", appKey);
param.Add("_timestamp", _timestamp.ToString());

string currentSign = SignHelper.GetSign(param, appKey);

if (_sign != currentSign)
{
result.ReturnCode = -2;
result.Message = "簽名不合法";
return GetHttpResponseMessage(result);
}
#endregion

var dataResult = stulist.Where(T => T.Age == age).ToList();
result.Result = dataResult;

return GetHttpResponseMessage(result);
}

?

4.接口參數加密+時效性驗證+私鑰(達到這個級別安全性固若金湯)

?繼上一步,你發現道高一尺魔高一丈,仍然有偷盜事情發生。咋辦呢?你打算下血本,給每個人配一把鑰匙的基礎上,再給每個人發個暗號,即使鑰匙被小偷弄去了,小偷沒有暗號,任然無法如愿,而且這樣很容易定位是誰的暗號泄漏問題,找到問題根源,只需要給當前這個人換下鑰匙就行了,不用大動干戈。

但這個并不是萬無一失的,因為鑰匙畢竟還有可能被小偷搞到。代碼如下:

/// <summary>
/// 接口加密并根據時間戳判斷有效性而且帶著私有key校驗
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("SecureBySign/Expired/KeySecret")]
public HttpResponseMessage SecureBySign_Expired_KeySecret([FromUri]int age, long _timestamp, string appKey, string _sign)
{
//key集合,這里隨便弄兩個測試數據
//如果調用方比較多,需要審核授權,根據一定的規則生成key把這些數據存放在數據庫中,如果功能擴展開來,可以針對不同的調用方做不同的功能權限管理
//在調用接口時動態從庫里取,每個調用方在調用時帶上他的key,調用方一般把自己的key放到網站配置中
Dictionary<string, string> keySecretDic = new Dictionary<string, string>();
keySecretDic.Add("key_zhangsan", "D9U7YY5D7FF2748AED89E90HJ88881E6");//張三的key,
keySecretDic.Add("key_lisi", "I9O6ZZ3D7FF2748AED89E90ZB7732M9");//李四的key

var result = new ResultModel<object>()
{
ReturnCode = 0,
Message = string.Empty,
Result = string.Empty
};

#region 判斷請求是否過期---假設過期時間是20秒
DateTime requestTime = GetDateTimeByTicks(_timestamp);

if (requestTime.AddSeconds(20) < DateTime.Now)
{
result.ReturnCode = -1;
result.Message = "接口過期";
return GetHttpResponseMessage(result);
}
#endregion

#region 根據appkey獲取key值
string secret = keySecretDic.Where(T => T.Key == appKey).FirstOrDefault().Value;
#endregion

#region 校驗簽名是否合法
var param = new SortedDictionary<string, string>(new AsciiComparer());
param.Add("age", age.ToString());
param.Add("appKey", appKey);

param.Add("appSecret", secret);//把secret加入進行加密

param.Add("_timestamp", _timestamp.ToString());

string currentSign = SignHelper.GetSign(param, appKey);

if (_sign != currentSign)
{
result.ReturnCode = -2;
result.Message = "簽名不合法";
return GetHttpResponseMessage(result);
}
#endregion

var dataResult = stulist.Where(T => T.Age == age).ToList();
result.Result = dataResult;

return GetHttpResponseMessage(result);
}

?

5.接口參數加密+時效性驗證+私鑰+Https(我把這個級別稱之為金鐘罩,世間最安全莫過于此)

繼上一步,我們給傳輸機制改為Https,這下小偷徹底懵逼了。那么問題來了,Https咋玩兒呢?可以在本地搭個環境,參考此文:http://www.cnblogs.com/naniannayue/archive/2012/11/19/2776948.html

?

另:本文的接口是用的MVC WebAPI寫的,完全基于RESTful標準。如對此不是特別了解可以參考此文:http://www.cnblogs.com/landeanfen/p/5501490.html

?

完整demo下載

?

注:demo不能直接運行,需要把兩個web項目配置到iis中,api代表接口提供方,他的主域需要配置到business的webconfig中,在瀏覽器地址欄分別請求business中的各個調用接口方法來實現接口調用。

1、如果想驗證接口超時,需要在請求接口時打個斷點把接口url取出,然后等到了超時時間,然后在瀏覽器中模擬請求

2、如果想驗證參數錯誤,需要在請求接口時打個斷點把接口url取出,篡改url參數,然后在瀏覽器中模擬請求

http://www.cnblogs.com/accumulater/p/6178166.html


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/272526.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/272526.shtml
英文地址,請注明出處:http://en.pswp.cn/news/272526.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux系統文件編程(1)

打開文件 int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode);open----返回的是文件描述符是整形數&#xff08;文件描述符在形式上是一個非負整數。實際上&#xff0c;它是一個索引值&#xff0c;指向內核為每一個進程所維…

【收集】常用的cmd命令

運行操作CMD命令&#xff1a;開始&#xff0d;>運行&#xff0d;>鍵入cmd或command(在命令行里可以看到系統版本、文件系統版本)CMD命令錦集1. gpedit.msc-----組策略2. sndrec32-------錄音機3. Nslookup-------IP地址偵測器 &#xff0c;是一個 監測網絡中 DNS 服務器是…

MVC框架詳解--Servlet+JSP+JavaBean模式(MVC)開發復雜的web應用

孤傲蒼狼 javaweb學習總結(二十二)——基于ServletJSPJavaBean開發模式的用戶登錄注冊 轉載于:https://www.cnblogs.com/yangjj08/p/10153657.html

Linux文件編程(2)

文件打開創建補充 &#xff08;1&#xff09;O_EXCL O_EXCL和O_CREAT配合使用 若文件不存在則創建文件 若文件存在則返回-1 代碼演示 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include<stdio.h> int main() {int fd;fdope…

IT技術人員必須思考的幾個問題

1.搞IT的是屌絲、碼農、程序猿?人們提到IT人的時候&#xff0c;總會想到他們呆板、不解風情&#xff0c;專注于IT技術&#xff0c;就算性感的美女躺在旁邊也無動于衷。事實真的是這樣嗎?雖說不能完全否定有這樣的情況存在&#xff0c;但這是IT人普遍的特點嗎?而其它行業也有…

37個JavaScript基本面試問題和解答

https://www.zcfy.cc/article/37-essential-javascript-interview-questions-and-answers1、使用typeof bar “object”來確定bar是否是一個對象時有什么潛在的缺陷&#xff1f;這個陷阱如何避免&#xff1f;盡管typeof bar “object”是檢查bar是否是對象的可靠方法&#xff0…

封裝cookie.js、EventUtil.js、

最近學習了javascript&#xff0c;封裝好的東西看起來舒服&#xff0c;以備需要的時候拉出來&#xff0c;jquery對javascript做了很好的封裝&#xff01;以后會多用jquery多些var CookieUtil {get: function (name){var cookieName encodeURIComponent(name) "",c…

實現linux cp 命令和修改配置文件

cp指令用來代碼的拷貝 以下由文件編程代碼實現 代碼演示 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include<stdio.h> #include <unistd.h> #include <string.h>#include <stdlib.h> int main(int argc…

最實用前端開發框架對比評測

現在&#xff0c;各種開發框架層出不窮&#xff0c;但是&#xff0c;真正的精品卻為數不多。今天我們根據Github上的流行程度整理了2014年最受歡迎的5個前端開發框架&#xff0c;并進行對比說明&#xff0c;希望幫助有需要的朋友選擇合適自己的前端框架。1. BootstrapBootstrap…

HBase1.0.0 實現數據增刪查

HBase1.0.0 即Hadoop 2.6 采用maven 的方式實現HBase數據簡單操作 import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Random;import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.a…

linux 寫結構體到文件

將整數寫入到文件 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include<stdio.h> #include <unistd.h> #include <string.h>#include <stdlib.h> int main() {int fd;int data100;int data20;fdopen("…

程序員常訪問的國外技術交流網站

技術人員經常會在各種技術交流社區游逛&#xff0c;大家互相學習、交流、分享、幫助。互聯網拉近了地球人的距離&#xff0c;讓全世界的技術人員可以聚集在一起分享交流。當然因為多方面原因&#xff0c;通常最新最權威的技術知識傳到國內存在一定“時差”。本文將給大家分享技…

標準C庫對文件操作的引入

modeopen和fopen的區別 fopen、fread、fwrite的使用 &#xff08;1&#xff09;fopen FILE *fopen(const char *path, const char *mode);path&#xff1a;文件路徑 mode&#xff1a;以什么權限打開&#xff0c;要用雙引號 它的返回值并不是文件描述符 若失敗返回NULL 若操作成…

轉載愛哥自定義View系列--Paint詳解

上圖是paint中的各種set方法 這些屬性大多我們都可以見名知意&#xff0c;很好理解&#xff0c;即便如此&#xff0c;哥還是帶大家過一遍逐個剖析其用法&#xff0c;其中會不定穿插各種繪圖類比如Canvas、Xfermode、ColorFilter等等的用法。 set(Paint src) 顧名思義為當前畫筆…

只有程序員才懂這些黑色幽默!

也是機緣巧合&#xff0c;讓我一個之前工作從未接觸過程序員的人&#xff0c;現在成天和程序員打交道&#xff0c;要知道&#xff0c;不懂技術&#xff0c;往往他們想和你幽默的搞笑一下&#xff0c;未必能讀懂。都說程序員情商低&#xff0c;不愛說話&#xff0c;比較悶騷。可…

tiny4412 linux+qtopia nfs網絡文件系統的掛載

1,首先確定uboot啟動內核的bootargs參數 Linux-CommandLine root/dev/nfs nfsroot192.168.1.131:/home/tiny4412/rootfs_qtopia_qt4 ip192.168.1.230:192.168.1.131:192.168.1.1:255.255.255.0::eth0:off rootfstypenfs consolettySAC0,115200 init/linuxrc ctp2 skipcaliy uh…

Linux 進程、父進程、子進程

進程和程序的區別 一、 進程是動態的&#xff0c;程序是靜態的&#xff1a;程序是有序代碼的集合&#xff0c;進程是程序的執行。進程有核心態/用戶態。 二、 進程是暫時的&#xff0c;程序是永久的&#xff1b;進程是一個狀態變化的過程&#xff0c;程序可以長久保存 三、進…

幾款開源富文本編輯器優缺點比較

1、百度UEditor 優點&#xff1a;插件多&#xff0c;基本滿足各種需求&#xff0c;類似貼吧中的回復界面。缺點&#xff1a;不再維護&#xff0c;文檔極少&#xff0c;使用并不普遍&#xff0c;圖片只能上傳到本地服務器&#xff0c;如果需要上傳到其他服務器需要改動源碼&…

C程序的儲存空間是如何分配?

可執行程序包括BSS段、數據段、代碼段。 在類UNIX系統下可使用size命令查看可執行文件的段大小信息。如size a.out&#xff1a; ~/Desktop/MyC$ size a.outtext data bss dec hex filename1672 600 8 2280 8e8 a.out1.數據段存放已初始化的全…

詳細講解Android的網絡通信(HttpUrlConnection和HttpClient)

前言&#xff0c;Android的網絡通信的方式有兩種&#xff1a;使用Socket或者HTTP&#xff0c;今天這一篇我們詳細講解使用HTTP實現的網絡通信&#xff0c;HTTP又包括兩種方式編程方式&#xff1a; &#xff08;1&#xff09;HttpUrlConnection&#xff1b; &#xff08;2&#…