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基本認證就是小編分享給年夜家的全體內容了,願望能給年夜家一個參考,也願望年夜家多多支撐。