Asp.net WebApi的授權安全機制 Basic認證
阿新 • • 發佈:2019-11-02
1:Home/index.cshtml下面的Html程式碼
<div> <input value="1點選先登陸" type="button" id="btnLogin"/><br /> <input value="2再點選授權後呼叫介面" type="button" id="btnAuthenrazation" /><br /> </div>
2:Home/index 下面的HomeController
[skipLogAttribute] public ActionResult Index() { return View(); }
3: Ajax的模擬程式碼,先登入,後獲取授權,再帶上Ticket,後臺過濾器校驗ok雜可以請求對應的介面
<script type="text/javascript"> $(function () { var ticket = ""; $("#btnLogin").click(function () { //---登陸的操作 $.ajax({ url: "http://localhost:8899/api/values", data: { "uid": "zrf", "pwd": "123" }, type: "get", success: function (res) { if (res.result) { ticket = res.ticket; alert("授權成功"+res.ticket); } }, dataType:"json" }) }); //----拿到了Ticket(後臺過濾器會判斷是否有過授權,以及授權ok才可以呼叫對應的介面) $("#btnAuthenrazation").click(function () { $.ajax({ url: "http://localhost:8899/api/values", data: { }, type: "get", beforeSend: function (xhr) { xhr.setRequestHeader('Authorization', 'BasicAuth ' + ticket);//--請求其他的介面都需要帶上Ticket的 }, success: function (res) { alert("ok") } }) }); }) //帶上Ticket來訪問WebApi介面 $("#btnWithTicket").click(function () { $.ajax({ url: "http://localhost:8899/api/values", data: {"id":110}, type: "get", beforeSend: function (xhr) { xhr.setRequestHeader('Authorization', 'BasicAuth ' + ticket);//--請求其他的介面都需要帶上Ticket的 }, success: function (res) { if (res.result) { alert("呼叫成功" + res.data); } } }) })
4: 建立的一個測試的 WebApiController 如ValuesController:ApiController
namespace WebApplication1.Controllers { using System.Web.Security; using WebApplication1.Filters; public class ValuesController : ApiController { [HttpGet] [skipLog] public dynamic Login(string uid, string pwd) { dynamic result = null; if ("zrf".Equals(uid) && pwd.Equals("123")) { FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, "account", DateTime.Now, DateTime.Now.AddSeconds(10), true, $"uid={uid},pwd={pwd}"); result = new { result = true, ticket = FormsAuthentication.Encrypt(ticket) }; } else { result = new { result = false, ticket = ""}; } return result; } // GET api/<controller> [skipLogAttribute] public IEnumerable<string> Get() { return new string[] { "value1", "value2" }; } // GET api/<controller>/5 [CustomerAuthenrazationFilter] public dynamic Get(int id) { return new { result = true, id = id }; } } }
5:授權過濾器:
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace WebApplication1.Filters { using System.Net.Http.Headers; using System.Web.Http.Controllers; using System.Web.Http.Filters; using System.Web.Security; using System.Web.Http; using System.Net; public class CustomerAuthenrazationFilterAttribute : AuthorizationFilterAttribute { public override void OnAuthorization(HttpActionContext actionContext) { skipLogAttribute skiplogin = actionContext.ActionDescriptor.GetCustomAttributes<skipLogAttribute>().FirstOrDefault(); if (skiplogin!=null) { return; } AuthenticationHeaderValue headevalue = actionContext.Request.Headers.Authorization; if (headevalue != null) { string Msg = string.Empty; if (ValidateTicket(headevalue.Parameter,out Msg)) { return; } else { this.HandlerUnAuthorization(Msg); } } else { this.HandlerUnAuthorization("請先獲取登陸授權的Ticket"); } } private void HandlerUnAuthorization(string Msg) { throw new Exception(Msg); } private bool ValidateTicket(string parameter,out string Msg) { Msg = string.Empty; if (!string.IsNullOrWhiteSpace(parameter)) { FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(parameter); if (ticket != null) { if (ticket.Expired) { Msg = "介面時間已經過期,請重新登陸授權!"; return false; } if (string.Equals($"uid=zrf,pwd=123", ticket.UserData))// $"uid={accountID},pwd={pwd}" { Msg = "授權成功!"; return true; } else { Msg = "授權失敗,請重新登陸授權!"; return false; } } } return false; } } }
6:自定義的特性,用來跳過許可權的驗證
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace WebApplication1.Filters { public class skipLogAttribute:Attribute { } }
7:在WebApiConfig 檔案中來註冊一個全域性的授權過濾器
namespace WebApplication1.App_Start { using System.Web.Mvc; public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API 配置和服務 // Web API 路由 config.MapHttpAttributeRoutes(); config.Filters.Add(new Filters.CustomerAuthenrazationFilterAttribute()); } } }
8:最後上兩張測試的截圖:
最後,這個案例只是起到拋磚引玉的作用,大家還可以做得更加的細緻及合理
如下:
我們還可以加上隨機字串:A;
時間戳:B(時間精確到秒,方便後續判斷,可過期);
唯一的uid C;
pwd D(根據uid來查詢資料庫並獲取到pwd),;
獲取自定義的簽名Sign:(如:uid+A+B+C+D 這4個值再MD5一下,防篡改),這樣就和微信那套機制就差不多了! 嘻嘻!
規則我們自己來定,歡迎大家提出有建議性的回覆,謝謝