活學活用,webapi HTTPBasicAuthorize搭建小型雲應用的實踐

來源:互聯網
上載者:User

標籤:

HTTP使用BASIC認證,WebAPI使用[HTTPBasicAuthorize]標記控制器就是使用了BASIC認證。 BASIC認證的缺點HTTP基本認證的目標是提供簡單的使用者驗證功能,其認證過程簡單明了,適合於對安全性要求不高的 系統或裝置中,如大家所用路由器的配置頁面的認證,幾乎 都採取了這種方式。其缺點是沒有靈活可靠的認證策略,如 無法提供域(domain或realm)認證功能,另外,BASE64的加密強度非常低,可以說僅 能防止sohu的搜尋把它搜到了。 當然,HTTP基本認證系統也可以與SSL或者Kerberos結合,實現安全效能較高(相對)的認證系統

難得的吐槽

逃回二線成都呆了兩年一直在做休閑娛樂行業的傳統管理軟體,由於該公司老闆太過於獨裁,反正股份分紅無望,幹得不爽。於是乎徹底逃出老家的縣城了。 半年來一直做了份遠端工作,非常感恩現在的BOSS,源了我在家辦公的心愿,雖然收入下降。 但是好在生活成本降低了許多,就是還個房貸和基本生活開銷、兩個寶貝上學的開銷。 還有就是接了一些私活,最近終於有空打算實現自己的產品夢了。我要做一套通用銷售計費軟體,原型已經做得七七八八了,就是架構上是單商戶的,不是多租戶的。 現在計劃是分布式應用架構,分傳統型程式端,安卓端,商戶平台端。由於前段時間客戶的用webapi和socket服務端做的中介軟體在ECS雲主機上不斷被攻擊,有一次居然把中介軟體程式搞死了。 所以這次使用WebAPI需要考慮使用安全防護機制了。 由於我這是個人的項目,太高深的安全防護肯定也是有門檻的。借鑒了銀聯POS協議,於是開始了這次的實踐。

主要驗證流程設計

1.用戶端 AuthenticationHeaderValue 請求的頭部

用戶端請求,規劃為 app_id:token,如下面例子就是在伺服器端使用"Request.Headers.Authorization.Parameter" 來擷取這個值,當然不能是明文吧,就是簡單的用Base64處理了下。

 using (var httpClient = new HttpClient())            {                var credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", "datacool_winform", "27C68F9A899842A598DDBACD2806FDD7")));                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);                string url = "http://" + MiddlewareIP + ":5990" + "/api/CloudPOS/GetVersion?k=" + Guid.NewGuid().ToString();                try                {                    string requestResult = httpClient.GetStringAsync(url).Result;                    return requestResult;                }                catch (Exception ex)                {                    Com.DataCool.DotNetExpand.LogHelper.Error(ex);                    return string.Empty;                }            }

 2.後台分需要授權驗證和不需要授權驗證的2個控制器

比如申請軟體試用,提交商戶門店資訊等就是不需要認證就可以發起請求,所以需要2個控制器

3.後台在資料庫裡控制和校正要求標頭部的app_id,token

後台就是寫一個類實現AuthorizeAttribute,即【HTTPBasicAuthorize】標示的攔截,代碼如下:

public class HTTPBasicAuthorizeAttribute : AuthorizeAttribute    {        /// <summary>        /// 校正Authorization        /// </summary>        /// <param name="actionContext"></param>        public override void OnAuthorization(HttpActionContext actionContext)        {            if (actionContext.Request.Headers.Authorization != null)            {                string[] agent_info = Encoding.Default.GetString(Convert.FromBase64String(actionContext.Request.Headers.Authorization.Parameter)).Split(":".ToArray());                //沒有按照預設的規則也是視為無權                if (agent_info.Length != 2)                {                    HandleUnauthorizedRequest(actionContext);                    return;                }                string request_agent = agent_info.FirstOrDefault();                string token = agent_info.LastOrDefault();                #region 資料庫校正app_id和token                using (var db = new POS_DB())                {                    try                    {                        db.Database.CreateIfNotExists();                    }                    catch { }                    #region 預設授權                    if (!db.sys_api_authorize.Any())                    {                        var dt = DateTime.Now;                        var sys_scheme = new sys_api_authorize                        {                            merchant_name = "DataCool",                            request_scheme = "afeng124",                            request_token = "15730052377",                            master_key = Guid.NewGuid().ToString().Replace("-", ""),                            create_dt = dt,                            last_request_dt = dt,                            status = 1                        };                        db.sys_api_authorize.Add(sys_scheme);                        db.Entry<sys_api_authorize>(sys_scheme).State = System.Data.Entity.EntityState.Added;                        db.SaveChanges();                    }                    #endregion                    var scheme_entity = db.sys_api_authorize                                        .Where(s => s.request_scheme == request_agent && s.request_token == token && s.status == 1)                                        .FirstOrDefault();                    if (scheme_entity != null)                    {                        scheme_entity.last_request_dt = DateTime.Now;                        db.SaveChanges();                        IsAuthorized(actionContext);                    }                    else                    {                        HandleUnauthorizedRequest(actionContext);                    }                }                #endregion            }            else            {                HandleUnauthorizedRequest(actionContext);            }        }        /// <summary>        /// 未通過認證,日誌進行記錄(發起請求的IP,請求的方法)        /// </summary>        /// <param name="actionContext"></param>        protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)        {            var challengeMessage = new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);            challengeMessage.Headers.Add("WWW-Authenticate", "Basic");            if (actionContext.Request.Headers.Authorization == null)            {                string ip = actionContext.Request.GetClientIpAddress();                var request_url = actionContext.Request.RequestUri.AbsoluteUri.ToString();                var request_obj = new                {                    RequestIP = ip,                    Request_Action = request_url,                    ErrorDesc = challengeMessage.StatusCode.ToString(),                    RequestMethod = actionContext.Request.Method.ToString(),                    Controller = actionContext.ControllerContext.ControllerDescriptor.ControllerName,                    RequestUrl = actionContext.Request.RequestUri.AbsoluteUri.ToString()                };                Com.DataCool.DotNetExpand.LogHelper.Error(request_obj);            }            base.HandleUnauthorizedRequest(actionContext);            //throw new HttpResponseException(challengeMessage);        }    }

上面如果直接throw會導致宿主服務程式異常,沒想到的是如果直接交給父類處理就行了。

沒通過認證那麼用戶端調用會出異常:

2016-10-09 17:02:39,916 層級:ERROR 日誌描述:System.AggregateException: 發生一個或多個錯誤。 ---> System.Net.Http.HttpRequestException: 響應狀態碼不指示成功: 401 (Unauthorized)。   --- 內部異常堆疊追蹤的結尾 ---   在 System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)   在 System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)   在 System.Threading.Tasks.Task`1.get_Result()   在 MiddlewareService.MiddlewareServiceSvr.HttpAPIRequest() 位置 D:\cloudservice\WebAPIService\MiddlewareServiceSvr.cs:行號 97---> (內部異常 #0) System.Net.Http.HttpRequestException: 響應狀態碼不指示成功: 401 (Unauthorized)。

瀏覽器類比get的樣子是這樣:

    

4.改造軟體的推廣方式和BASIC認證結合起來

這個思路主要是這樣的:

1.商戶在官網上下載用戶端軟體前先申請試用,提交商戶的基本資料,這是營銷和售前服務的基礎。

2.商戶提交試用申請後下載傳統型程式,傳統型程式啟用一下調用api擷取主要金鑰和app_id和token。

3.登入商戶後台設定門店基礎參數。

4.伺服器可以控制使用到期日和功能

活學活用,webapi HTTPBasicAuthorize搭建小型雲應用的實踐

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.