Web API身份認(rèn)證解決方案之Basic基礎(chǔ)認(rèn)證
一、WebApi中為什么需要身份認(rèn)證
我們?cè)谑褂肳ebApi的時(shí)候,都是通過(guò)URL去獲取數(shù)據(jù)。也就是說(shuō),任何人只要知道了URL地址,就能隨意的訪問(wèn)后臺(tái)的服務(wù)接口,就可以訪問(wèn)或者修改數(shù)據(jù)庫(kù)數(shù)據(jù)了,這樣就會(huì)導(dǎo)致很嚴(yán)重的后果。
1、我們不加身份認(rèn)證,匿名用戶可以直接通過(guò)url隨意訪問(wèn)接口:
2、增加了身份認(rèn)證之后,只有帶了票據(jù)的請(qǐng)求才能訪問(wèn)對(duì)應(yīng)的接口。
二、常見的認(rèn)證方式
WebApi中常見的認(rèn)證方式有如下幾種:
- FORM身份驗(yàn)證
- 集成WINDOWS驗(yàn)證
- Basic基礎(chǔ)認(rèn)證
- Digest摘要認(rèn)證
三、Basic基礎(chǔ)認(rèn)證
Basic基礎(chǔ)認(rèn)證原理
Basic認(rèn)證的基本原理就是加密用戶信息生成Ticket,每次請(qǐng)求后端API接口的時(shí)候把生成的Ticket信息加到http請(qǐng)求的頭部傳給后端進(jìn)行驗(yàn)證。具體步驟如下:
- 1、登錄的時(shí)候驗(yàn)證用戶名和密碼,如果驗(yàn)證通過(guò),則將用戶名和密碼按照一定的規(guī)則生成加密后的票據(jù)信息Ticket,然后將Ticket傳遞到前端。
- 2、如果登錄成功,前端定義一個(gè)全局的變量接收API接口返回的Ticket信息。
- 3、前端界面再次發(fā)起ajax請(qǐng)求后端API接口的時(shí)候,將Ticket信息加入到HTTP請(qǐng)求的Head里面,將Ticket信息隨著http請(qǐng)求一起發(fā)送到后端API接口。
- 4、在后端的WebApi服務(wù)中定義一個(gè)類,該類繼承自AuthorizeAttribute類,然后重新父類里面的OnAuthorization方法,在OnAuthorization方法里面,通過(guò)actionContext參數(shù)取得http請(qǐng)求的Head,從Head里面可以獲取前端傳遞過(guò)來(lái)的Ticket信息。將Ticket解密得到用戶名和密碼,然后驗(yàn)證用戶名和密碼是否正確。如果正確,表示驗(yàn)證通過(guò)。如果不正確,則返回401未授權(quán)的錯(cuò)誤。
四、Basic基礎(chǔ)認(rèn)證示例代碼
假設(shè)我們要訪問(wèn)Users控制器的Get接口,該接口方法返回int類型的List集合。
1、登錄的API接口
using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; using System.Web.Security; using WebApiBasicAuthorize.CustomerAttribute; using WebApiBasicAuthorize.Entity; namespace WebApiBasicAuthorize.Controllers { [BasicAuthorize] public class UsersController : ApiController { /// <summary> /// 允許匿名登錄 /// </summary> /// <param name="account"></param> /// <param name="password"></param> /// <returns></returns> [AllowAnonymous] [HttpGet] public IHttpActionResult Login(string account,string password) { ReturnValueEntity entity = new ReturnValueEntity(); // 真實(shí)生產(chǎn)環(huán)境中要去數(shù)據(jù)庫(kù)校驗(yàn)account和password if (account.ToUpper().Trim().Equals("ADMIN") && password.Trim().Equals("123456")) { FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(0, account, DateTime.Now, DateTime.Now.AddHours(1), true, string.Format("{0}&{1}", account, password), FormsAuthentication.FormsCookiePath); var result = new { Result = true, Ticket = FormsAuthentication.Encrypt(ticket) }; entity.Result = true; entity.Ticket = FormsAuthentication.Encrypt(ticket); } else { entity.Result = false; entity.Ticket = ""; } return Json<ReturnValueEntity>(entity); } [HttpGet] public IHttpActionResult Get() { List<int> list = new List<int>(); list.Add(1); list.Add(2); list.Add(3); list.Add(4); list.Add(5); return Json<List<int>>(list); } } }
在Login方法上面添加 [AllowAnonymous]特性,表示允許匿名登錄。
2、基礎(chǔ)認(rèn)證接口
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Http; using System.Web.Http.Controllers; using System.Web.Security; namespace WebApiBasicAuthorize.CustomerAttribute { /// <summary> /// 自定義特性繼承自AuthorizeAttribute /// </summary> public class BasicAuthorizeAttribute:AuthorizeAttribute { public override void OnAuthorization(HttpActionContext actionContext) { // 從當(dāng)前http請(qǐng)求Request對(duì)象的頭部信息里面獲取Authorization屬性 var authorization = actionContext.Request.Headers.Authorization; // 判斷控制器獲取action方法上面是否有AllowAnonymousAttribute特性,如果有,則允許匿名登錄 if (actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>(true).Count != 0 || actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>(true).Count != 0) { base.OnAuthorization(actionContext); } else if (authorization != null && authorization.Parameter != null) { // 驗(yàn)證用戶邏輯 if (ValidateTicket(authorization.Parameter)) { // 驗(yàn)證通過(guò) base.IsAuthorized(actionContext); } else { this.HandleUnauthorizedRequest(actionContext); } } else { // 返回401沒(méi)有授權(quán)的狀態(tài)碼 this.HandleUnauthorizedRequest(actionContext); } } /// <summary> /// 驗(yàn)證Ticket信息 /// </summary> /// <param name="encryptTicket"></param> /// <returns></returns> private bool ValidateTicket(string encryptTicket) { // 解密Ticket var strTicket = FormsAuthentication.Decrypt(encryptTicket).UserData; // 從Ticket里面獲取用戶名和密碼 int index = strTicket.IndexOf("&"); //string strUser=strTicket string[] array = strTicket.Split('&'); string strUser = array[0]; string strPwd = array[1]; // 真實(shí)生產(chǎn)環(huán)境中應(yīng)該用解密的用戶名和密碼去數(shù)據(jù)庫(kù)驗(yàn)證,這里為了演示方便 // 假定用戶名是Admin,密碼是123456 if(strUser.Equals("Admin")&&strPwd.Equals("123456")) { return true; } else { return false; } } } }
3、前端代碼
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>權(quán)限認(rèn)證</title> <script src="jquery-1.10.2.min.js"></script> <script> // 定義全局的ticket變量,用來(lái)保存登錄成功以后的Ticket值 var ticket; window.onload=function(){ }; function Login(){ $.ajax({ url:"http://localhost:20033/api/users?account="+$("#acc").val().trim()+"&password="+$("#pwd").val().trim(), type:"Get", dataType:"json", "headers": { "Content-Type": "application/json", "cache-control": "no-cache" }, success:function(data){ if(result.Result){ ticket=data.Ticket; }else{ alert("失敗"); } }, error:function(data){ alert(data); } }); }; function Test(){ alert(ticket); $.ajax({ url:'http://localhost:20033/api/users', type:"Get", dataType:"json", beforeSend:function(XHR){ //發(fā)送ajax請(qǐng)求之前向http的head里面加入驗(yàn)證信息 XHR.setRequestHeader('Authorization','BasicAuth '+ticket); }, success:function(data){ alert(data); }, error:function(data){ alert(data); } }); }; </script> </head> <body> <div> <div> <label>用戶名:</label> <input type="text" id="acc"> </div> <div> <label>密碼:</label> <input type="password" id="pwd"> </div> <div> <input type="button" id="btnLogin" onclick="Login()" value="登錄"> </div> <div> <input type="button" id="GetAccount" onclick="Test()" value="測(cè)試"> </div> </div> </body> </html>
這里需要說(shuō)明的是,我們?cè)诎l(fā)送ajax請(qǐng)求之前,通過(guò)XHR.setRequestHeader('Authorization', 'BasicAuth ' + Ticket); 這句向http請(qǐng)求的Head里面添加Ticket信息。
通過(guò)上面的幾步就可以達(dá)到Basic認(rèn)證的效果了。
注意:后端的WebApi接口要配置允許跨域訪問(wèn)。
4、優(yōu)化
每增加一個(gè)控制器,都需要在相應(yīng)的控制器上面加[BasicAuthorize]特性,可以定義一個(gè)公共的控制器父類,該父類繼承自ApiController,然后其他控制器繼承該父類。
到此這篇關(guān)于Web API身份認(rèn)證解決方案之Basic基礎(chǔ)認(rèn)證的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- C#進(jìn)階系列 WebApi身份認(rèn)證解決方案推薦:Basic基礎(chǔ)認(rèn)證
- .net使用jwt進(jìn)行身份認(rèn)證的流程記錄
- asp.net core3.1cookie和jwt混合認(rèn)證授權(quán)實(shí)現(xiàn)多種身份驗(yàn)證方案
- 深入解讀ASP.NET Core身份認(rèn)證過(guò)程實(shí)現(xiàn)
- Asp.net Core中實(shí)現(xiàn)自定義身份認(rèn)證的示例代碼
- ASP.NET Forms身份認(rèn)證
- 在ASP.NET Core中實(shí)現(xiàn)一個(gè)Token base的身份認(rèn)證實(shí)例
- 淺談如何在ASP.NET Core中實(shí)現(xiàn)一個(gè)基礎(chǔ)的身份認(rèn)證
- 關(guān)于C#.net winform程序驗(yàn)證moss的集成身份認(rèn)證實(shí)例
相關(guān)文章
詳解Asp.Net Core 2.1+的視圖緩存(響應(yīng)緩存)
本篇文章給大家通過(guò)實(shí)例講述了Asp.Net Core 2.1+的視圖緩存(響應(yīng)緩存)的相關(guān)知識(shí)點(diǎn),對(duì)此有興趣的讀者們可以學(xué)習(xí)下。2018-03-03.NET Core如何進(jìn)行請(qǐng)求轉(zhuǎn)發(fā)的實(shí)現(xiàn)
這篇文章主要介紹了.NET Core如何進(jìn)行請(qǐng)求轉(zhuǎn)發(fā)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11ASP.NET網(wǎng)站聊天室的設(shè)計(jì)與實(shí)現(xiàn)(第3節(jié))
這篇文章主要介紹了ASP.NET網(wǎng)站聊天室的設(shè)計(jì)與實(shí)現(xiàn),了解Session、Application對(duì)象的屬性和事件,并且掌握利用它們?cè)陧?yè)面間保存和傳遞數(shù)據(jù)的方法,需要的朋友可以參考下2015-08-08EF使用Code First模式給實(shí)體類添加復(fù)合主鍵
這篇文章介紹了EF使用Code First模式給實(shí)體類添加復(fù)合主鍵的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03Repeater的FooterTemplate中控件內(nèi)容設(shè)置方法
Repeater的FooterTemplate中控件內(nèi)容設(shè)置方法,需要的朋友可以參考下。2009-12-12asp.net 實(shí)現(xiàn)動(dòng)態(tài)顯示當(dāng)前時(shí)間(不用javascript不考慮開銷)
asp.net實(shí)現(xiàn)動(dòng)態(tài)顯示時(shí)間,無(wú)需用到j(luò)avascrip,而是用了AJAX。2009-11-11