Web API身份認(rèn)證解決方案之Basic基礎(chǔ)認(rèn)證
一、WebApi中為什么需要身份認(rèn)證
我們?cè)谑褂肳ebApi的時(shí)候,都是通過URL去獲取數(shù)據(jù)。也就是說,任何人只要知道了URL地址,就能隨意的訪問后臺(tái)的服務(wù)接口,就可以訪問或者修改數(shù)據(jù)庫數(shù)據(jù)了,這樣就會(huì)導(dǎo)致很嚴(yán)重的后果。
1、我們不加身份認(rèn)證,匿名用戶可以直接通過url隨意訪問接口:

2、增加了身份認(rèn)證之后,只有帶了票據(jù)的請(qǐng)求才能訪問對(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ī)則生成加密后的票據(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方法里面,通過actionContext參數(shù)取得http請(qǐng)求的Head,從Head里面可以獲取前端傳遞過來的Ticket信息。將Ticket解密得到用戶名和密碼,然后驗(yàn)證用戶名和密碼是否正確。如果正確,表示驗(yàn)證通過。如果不正確,則返回401未授權(quán)的錯(cuò)誤。
四、Basic基礎(chǔ)認(rèn)證示例代碼
假設(shè)我們要訪問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ù)庫校驗(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)證通過
base.IsAuthorized(actionContext);
}
else
{
this.HandleUnauthorizedRequest(actionContext);
}
}
else
{
// 返回401沒有授權(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ù)庫驗(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變量,用來保存登錄成功以后的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>這里需要說明的是,我們?cè)诎l(fā)送ajax請(qǐng)求之前,通過XHR.setRequestHeader('Authorization', 'BasicAuth ' + Ticket); 這句向http請(qǐng)求的Head里面添加Ticket信息。
通過上面的幾步就可以達(dá)到Basic認(rèn)證的效果了。
注意:后端的WebApi接口要配置允許跨域訪問。
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)證過程實(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)文章
.NET?7?AOT?的使用及?.NET?與?Go?互相調(diào)用的過程
本文主要介紹如何在.NET和Go語言中如何生成系統(tǒng)(Windows)動(dòng)態(tài)鏈接庫,又如何從代碼中引用這些庫中的函數(shù),在文章中會(huì)演示.NET和Go相互調(diào)用各自生成的動(dòng)態(tài)鏈接庫,以及對(duì)比兩者之間的差異,感興趣的朋友一起看看吧2024-12-12
IIS7偽靜態(tài)web.config配置的方法和規(guī)則
本文主要介紹IIS7上配置偽靜態(tài)的超簡(jiǎn)單的新方法,安裝URLRewrite插件,配置web.config即可。2016-04-04
用擴(kuò)展方法優(yōu)化多條件查詢(不定條件查詢)
在我們開發(fā)過程中,特別是管理系統(tǒng)的開發(fā),經(jīng)常會(huì)遇到多條件查詢(或者叫不定條件查詢)的案例,就是提供給User輸入的查詢條件有多個(gè)不同的查詢欄位,而且,在實(shí)際使用中并不能確定User會(huì)使用哪些條件來當(dāng)做搜索條件2012-12-12
Gridview使用CheckBox全選與單選采用js實(shí)現(xiàn)同時(shí)高亮顯示選擇行
Gridview使用CheckBox單選與全選功能再次進(jìn)行簡(jiǎn)單演示,選中的行,使用高亮顯示,讓用戶一目了然看到哪一行被選擇了,在項(xiàng)目中很實(shí)用的,開發(fā)中的朋友們可要考慮一下哦2013-01-01
asp.net 安全的截取指定長(zhǎng)度的html或者ubb字符串
在將html代碼輸出到頁面時(shí),有時(shí)候會(huì)需要截?cái)嘧址A糁付ㄩL(zhǎng)度的字符串,由于html中有些標(biāo)簽必須成對(duì)出現(xiàn),所以在截取html時(shí)需要特別注意,不能因?yàn)榻財(cái)鄦栴}把頁面搞亂掉。2010-01-01
充分利用ASP.NET的三種緩存提高站點(diǎn)性能的注意方法
充分利用ASP.NET的三種緩存提高站點(diǎn)性能的注意方法...2007-09-09
淺談.NET中加密和解密的實(shí)現(xiàn)方法分享
這篇文章介紹了.NET中加密和解密的實(shí)現(xiàn)方法,有需要的朋友可以參考一下2013-11-11
詳解在ASP.NET Core中使用Angular2以及與Angular2的Token base身份認(rèn)證
這篇文章主要介紹了詳解在ASP.NET Core中使用Angular2以及與Angular2的Token base身份認(rèn)證,有興趣的可以了解一下。2016-12-12

