C#進階系列 WebApi身份認證處理計劃推舉:Basic基本認證。本站提示廣大學習愛好者:(C#進階系列 WebApi身份認證處理計劃推舉:Basic基本認證)文章只能為提供參考,不一定能成為您想要的結果。以下是C#進階系列 WebApi身份認證處理計劃推舉:Basic基本認證正文
媒介:比來,評論辯論到數據庫平安的成績,因而就引出了WebApi辦事沒有加任何驗證的成績。也就是說,任何人只需曉得了接口的url,都可以或許模仿http要求去拜訪我們的辦事接口,從而去增刪改查數據庫,這效果想一想都恐懼。經由一番折騰,總算是加上了接口的身份認證,在此記載下,也給須要做身份認證的園友們供給參考。
1、為何須要身份認證
在媒介外面,我們說了,假如沒有啟用身份認證,那末任何匿名用戶只需曉得了我們辦事的url,就可以隨便拜訪我們的辦事接口,從而拜訪或修正數據庫。
1、我們不加身份認證,匿名用戶可以直接經由過程url隨便拜訪接口:
可以看到,匿名用戶直接經由過程url就可以拜訪我們的數據接口,終究會產生甚麼事,年夜家可以隨便暢想。
2、增長了身份認證以後,只要帶了我們拜訪單子的要求能力拜訪我們的接口。
例如我們直接經由過程url拜訪,會前往401
假如是正常流程的要求,帶了單子,就OK了。
可以看到,正常流程的要求,會在要求報文的頭外面增長Authorization這一項,它的值就是我們的Ticket單子信息。
2、Basic基本認證的道理解析
1、罕見的認證方法
我們曉得,asp.net的認證機制有許多種。關於WebApi也不破例,罕見的認證方法有
園子裡許多關於WebApi認證的文章,各類認證方法都邑觸及到,但感到都不敷細。這裡也其實不想去研討哪一種驗證方法實用哪一種應用場景,由於博主照樣認為“貪多嚼不爛”,也能夠是博主才能所限。關於認證機制,弄懂個中一種,其他的都能融合貫穿。此篇就應用Basic基本認證來具體講授下全部的進程。
2、Basic基本認證道理
我們曉得,認證的目標在於平安,那末若何能包管平安呢?經常使用的手腕天然是加密。Basic認證也不破例,重要道理就是加密用戶信息,生成單子,每次要求的時刻將單子帶過去驗證。如許說能夠有點籠統,我們具體分化每一個步調:
這個根本的道理。上面就依照這個道理來看看每步的代碼若何完成。
3、Basic基本認證的代碼示例
起首說下我們的示例場景,前次引見 CORS 的時刻我們在一個處理計劃外面放了兩個項目Web和WebApiCORS,我們此次照樣以這個為例來講明。
1、登錄進程1.1、Web前端
<body> <div > <div>用戶名:<input type="text" id="txt_username" /></div> <div>密 碼:<input type="password" id="txt_password" /></div> <div><input type="button" value="登錄" id="btn_login" class="btn-default" /></div> </div> </body>
$(function () { $("#btn_login").click(function () { $.ajax({ type: "get", url: "http://localhost:27221/api/User/Login", data: { strUser: $("#txt_username").val(), strPwd: $("#txt_password").val() }, success: function (data, status) { if (status == "success") { if (!data.bRes){ alert("登錄掉敗"); return; } alert("登錄勝利"); //登錄勝利以後將用戶名和用戶單子帶到主界面 window.location = "/Home/Index?UserName=" + data.UserName + "&Ticket=" + data.Ticket; } }, error: function (e) { }, complete: function () { } }); }); });
1.2、登錄的API接口
public class UserController : ApiController { /// <summary> /// 用戶登錄 /// </summary> /// <param name="strUser"></param> /// <param name="strPwd"></param> /// <returns></returns> [HttpGet] public object Login(string strUser, string strPwd) { if (!ValidateUser(strUser, strPwd)) { return new { bRes = false }; } FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(0, strUser, DateTime.Now, DateTime.Now.AddHours(1), true, string.Format("{0}&{1}", strUser, strPwd), FormsAuthentication.FormsCookiePath); //前往登錄成果、用戶信息、用戶驗證單子信息 var oUser = new UserInfo { bRes = true, UserName = strUser, Password = strPwd, Ticket = FormsAuthentication.Encrypt(ticket) }; //將身份信息保留在session中,驗證以後要求能否是有用要求 HttpContext.Current.Session[strUser] = oUser; return oUser; } //校驗用戶名暗碼(正式情況中應當是數據庫校驗) private bool ValidateUser(string strUser, string strPwd) { if (strUser == "admin" && strPwd == "123456") { return true; } else { return false; } } } public class UserInfo { public bool bRes { get; set; } public string UserName { get; set; } public string Password { get; set; } public string Ticket { get; set; } }
這裡有一點須要留意的是,由於WebApi默許是沒有開啟Session的,所以須要我們作一下設置裝備擺設,手動去啟用session。
正如下面的道理部門說的,登錄假如掉敗,則直接前往;假如勝利,則將生成的單子Ticket帶到前端,傳到主界面/Home/Index,上面,我們就來看看主界面Home/Index。
2、/Home/Index主界面
public class HomeController : Controller { // GET: Home public ActionResult Index(string UserName, string Ticket) { ViewBag.UserName = UserName; ViewBag.Ticket = Ticket; return View(); } }
<html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> <script src="~/Content/jquery-1.9.1.js"></script> <link href="~/Content/bootstrap/css/bootstrap.css" rel="stylesheet" /> <script src="~/Content/bootstrap/js/bootstrap.js"></script> <script src="~/Scripts/Home/Index.js"></script> <script type="text/javascript"> //翻開頁面的時刻保留單子信息 var UserName = '@ViewBag.UserName'; var Ticket = '@ViewBag.Ticket'; </script> </head> <body> <div>以後登錄用戶:'@ViewBag.UserName'</div> <div id="div_test"> </div> </body> </html>
$(function () { $.ajax({ type: "get", url: "http://localhost:27221/api/Charging/GetAllChargingData", data: {}, beforeSend: function (XHR) { //發送ajax要求之前向http的head外面參加驗證信息 XHR.setRequestHeader('Authorization', 'BasicAuth ' + Ticket); }, success: function (data, status) { if (status == "success") { $("#div_test").html(data); } }, error: function (e) { $("#div_test").html("Error"); }, complete: function () { } }); });
這裡須要解釋的是,我們在發送ajax要求之前,經由過程 XHR.setRequestHeader('Authorization', 'BasicAuth ' + Ticket); 這一句向要求的報文頭外面增長單子信息。就是由於這裡加了這一句,所以才有我們下圖中的紅線部門:
3、WebApiCORS驗證部門(重點)
我們看到,下面的/Home/Index頁面外面發送了ajax要求去拜訪辦事的 http://localhost:27221/api/Charging/GetAllChargingData 這個接口,那末我們在WebApi外面怎樣去驗證這個要求和正當的要求呢?接上去我們重點看看驗證的這個進程。
3.1、在WebApiCORS項目外面自界說一個類RequestAuthorizeAttribute,去繼續我們的AuthorizeAttribute這個類。然後重寫OnAuthorization辦法,在這個辦法外面取到要求頭的Ticket信息,然後校驗用戶名暗碼能否公道。
/// <summary> /// 自界說此特征用於接口的身份驗證 /// </summary> public class RequestAuthorizeAttribute : AuthorizeAttribute { //重寫基類的驗證方法,參加我們自界說的Ticket驗證 public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext) { //從http要求的頭外面獲得身份驗證信息,驗證能否是要求提議方的ticket var authorization = actionContext.Request.Headers.Authorization; if ((authorization != null) && (authorization.Parameter != null)) { //解密用戶ticket,並校驗用戶名暗碼能否婚配 var encryptTicket = authorization.Parameter; if (ValidateTicket(encryptTicket)) { base.IsAuthorized(actionContext); } else { HandleUnauthorizedRequest(actionContext); } } //假如取不到身份驗證信息,而且不許可匿名拜訪,則前往未驗證401 else { var attributes = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>(); bool isAnonymous = attributes.Any(a => a is AllowAnonymousAttribute); if (isAnonymous) base.OnAuthorization(actionContext); else HandleUnauthorizedRequest(actionContext); } } //校驗用戶名暗碼(正式情況中應當是數據庫校驗) private bool ValidateTicket(string encryptTicket) { //解密Ticket var strTicket = FormsAuthentication.Decrypt(encryptTicket).UserData; //從Ticket外面獲得用戶名和暗碼 var index = strTicket.IndexOf("&"); string strUser = strTicket.Substring(0, index); string strPwd = strTicket.Substring(index + 1); if (strUser == "admin" && strPwd == "123456") { return true; } else { return false; } } }
3.2、在詳細的Api接口增長我們下面自界說類的特征
[RequestAuthorize] public class ChargingController : ApiController { /// <summary> /// 獲得一切數據 /// </summary> /// <returns>前往數據</returns> [HttpGet] public string GetAllChargingData() { return "Success"; } /// <summary> /// 獲得以後Id的一切數據 /// </summary> /// <param name="id">參數Id</param> /// <returns>前往數據</returns> [HttpGet] public string GetAllChargingData(string id) { return "ChargingData" + id; } }
增長了特征標注以後,每次要求這個API外面的接口之前,法式會先輩入到我們override過的 OnAuthorization() 辦法外面,驗證經由過程以後,才會進到響應的辦法外面去履行,不然前往401。
4、優化
經由過程下面的幾步,根本就可以到達我們想要的身份認證的後果,然則老是感到不太便利,重要不太便利的點有以下幾個。
1.每次新建一個API,對應的接口下面都要標注 [RequestAuthorize] 這個一個器械,感到好費事。
2.每次發送ajax要求,都要在beforeSend事宜外面加 XHR.setRequestHeader('Authorization', 'BasicAuth ' + Ticket); 這個,感到也費事。
關於以上兩點,我們優化下
1、處理API的成績
在API外面加一個公共的父類,在父類下面標注 [RequestAuthorize] 便可。
namespace WebApiCORS.Controllers { [RequestAuthorize] [EnableCors(origins: "*", headers: "*", methods: "*")] public class BaseApiController : ApiController { } }
namespace WebApiCORS.Controllers { public class ChargingController : BaseApiController { /// <summary> /// 獲得一切數據 /// </summary> /// <returns>前往數據</returns> [HttpGet] public string GetAllChargingData() { return "Success"; } /// <summary> /// 獲得以後Id的一切數據 /// </summary> /// <param name="id">參數Id</param> /// <returns>前往數據</returns> [HttpGet] public string GetAllChargingData(string id) { return "ChargingData" + id; } } }
留意:我們登錄的要求是不須要驗證的,由於登錄的時刻還沒有發生單子,所以登錄的API不克不及夠繼續 BaseApiController
2、處理ajax的成績
還記得我們在 JS組件系列——封裝本身的JS組件,你也能夠 這篇外面引見的增長ajax的error事宜的公共處置辦法嗎?我們能否也能夠經由過程異樣的機制去增長這個呢。新建一個文件Jquery_ajax_extention.js
(function ($) { //1.獲得$.ajax的對象 var _ajax = $.ajax; $.ajax = function (options) { //2.每次挪用發送ajax要求的時刻界說默許的error處置辦法 var fn = { error: function (XMLHttpRequest, textStatus, errorThrown) { toastr.error(XMLHttpRequest.responseText, '毛病新聞', { closeButton: true, timeOut: 0, positionClass: 'toast-top-full-width' }); }, success: function (data, textStatus) { }, beforeSend: function (XHR) { }, complete: function (XHR, TS) { } } //3.擴大原生的$.ajax辦法,前往最新的參數 var _options = $.extend({}, { error: function (XMLHttpRequest, textStatus, errorThrown) { fn.error(XMLHttpRequest, textStatus, errorThrown); }, success: function (data, textStatus) { fn.success(data, textStatus); }, beforeSend: function (XHR) { XHR.setRequestHeader('Authorization', 'BasicAuth ' + Ticket); fn.beforeSend(XHR); }, complete: function (XHR, TS) { fn.complete(XHR, TS); } }, options); //4.將最新的參數傳回ajax對象 _ajax(_options); }; })(jQuery);
援用這個js後再發送ajax不用在每一個要求的beforeSend外面寫了。
5、總結
以上聯合一個實例講授了下Basic認證的完成道理和簡略應用,本文不雅點都是來自博主本身的懂得,假如有不周全的處所,還望園友們示正。假如本文可以或許或多或少幫到你,無妨協助推舉
以上這篇C#進階系列 WebApi身份認證處理計劃推舉:Basic基本認證就是小編分享給年夜家的全體內容了,願望能給年夜家一個參考,也願望年夜家多多支撐。