ASP.NET MVC API 接口驗(yàn)證的示例代碼
項(xiàng)目中有一個(gè)留言消息接口,接收其他系統(tǒng)的留言和展示留言,參考了網(wǎng)上的一些API驗(yàn)證方法,發(fā)現(xiàn)使用通用權(quán)限管理系統(tǒng)提供的驗(yàn)證方法最完美。
下面將實(shí)現(xiàn)的完整思路共享
1、WebApiConfig全局處理
/// <summary>
/// WebApiConfig
/// 路由基礎(chǔ)配置。
///
///
/// 修改記錄
///
/// 2016.11.01 版本:2.0 宋彪 對日期格式進(jìn)行統(tǒng)一處理。
/// 2016.10.30 版本:2.0 宋彪 解決json序列化時(shí)的循環(huán)引用問題。
/// 2016.10.28 版本:2.0 宋彪 回傳響應(yīng)格式 $format 支持。
/// 2016.09.01 版本:1.0 宋彪 創(chuàng)建。
///
/// 版本:1.0
///
/// <author>
/// <name>宋彪</name>
/// <date>2016.09.01</date>
/// </author>
/// </summary>
public static class WebApiConfig
{
/// <summary>
/// 注冊全局配置服務(wù)
/// </summary>
/// <param name="config"></param>
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
//強(qiáng)制https訪問
//config.Filters.Add(new ForceHttpsAttribute());
// 統(tǒng)一回傳格式
config.Filters.Add(new ApiResultAttribute());
// 發(fā)生異常時(shí)處理
config.Filters.Add(new ApiErrorHandleAttribute());
// ToKen身份驗(yàn)證過濾器 更方便 不需要在這里了 具有改標(biāo)簽的就會(huì)自動(dòng)檢查
//config.Filters.Add(new ApiAuthFilterAttribute());
// 解決json序列化時(shí)的循環(huán)引用問題
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
//對日期格式進(jìn)行統(tǒng)一處理
config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(
new IsoDateTimeConverter()
{
DateTimeFormat = "yyyy-MM-dd hh:mm:ss"
}
);
// Web API routes 路由
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
// 干掉XML序列化器
//config.Formatters.Remove(config.Formatters.XmlFormatter);
//在請求的Url加上 ?$format=xml,便可以指定響應(yīng)格式
config.Formatters.XmlFormatter.AddQueryStringMapping("$format", "xml", "application/xml");
config.Formatters.JsonFormatter.AddQueryStringMapping("$format", "json", "application/json");
}
}
2、身份驗(yàn)證過濾器
using DotNet.Business;
using DotNet.Utilities;
using DotNet.Tracking.API.Common;
/// <summary>
/// ApiAuthFilterAttribute
/// 身份驗(yàn)證過濾器,具有ApiAuthFilterAttribute標(biāo)簽屬性的方法會(huì)自動(dòng)檢查
///
///
/// 修改紀(jì)錄
///
/// 2016-10-11 版本:1.0 SongBiao 創(chuàng)建文件。
///
/// <author>
/// <name>SongBiao</name>
/// <date>2016-10-11</date>
/// </author>
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class ApiAuthFilterAttribute : AuthorizationFilterAttribute
{
/// <summary>
/// 未授權(quán)時(shí)的提示信息
/// </summary>
private const string UnauthorizedMessage = "請求未授權(quán),拒絕訪問。";
/// <summary>
/// 權(quán)限進(jìn)入
/// </summary>
/// <param name="actionContext"></param>
public override void OnAuthorization(HttpActionContext actionContext)
{
base.OnAuthorization(actionContext);
// 允許匿名訪問
if (actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Count > 0)
{
return;
}
string systemCode = APIOperateContext.Current.SystemCode;
string permissionCode = APIOperateContext.Current.PermissionCode;
string appKey = APIOperateContext.Current.AppKey;
string appSecret = APIOperateContext.Current.AppSecret;
if (string.IsNullOrWhiteSpace(appKey) || string.IsNullOrWhiteSpace(appSecret))
{
//未驗(yàn)證(登錄)的用戶, 而且是非匿名訪問,則轉(zhuǎn)向登錄頁面
//actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
//actionContext.Response.Content = new StringContent("<p>Unauthorized</p>", Encoding.UTF8, "text/html");
var response = actionContext.Response= actionContext.Response?? new HttpResponseMessage();
response.StatusCode = HttpStatusCode.Unauthorized;
BaseResult result = new BaseResult
{
Status = false,
StatusMessage = UnauthorizedMessage
};
response.Content = new StringContent(result.ToJson(), Encoding.UTF8, "application/json");
}
else
{
// 檢查 AppKey 和 AppSecret
BaseResult result = BaseServicesLicenseManager.CheckService(appKey, appSecret, false, 0, 0, systemCode, permissionCode);
if (!result.Status)
{
var response = actionContext.Response = actionContext.Response?? new HttpResponseMessage();
response.Content = new StringContent(result.ToJson(), Encoding.UTF8, "application/json");
}
}
}
}
3、統(tǒng)一回傳格式
/// <summary>
/// ApiResultAttribute
/// 統(tǒng)一回傳格式
///
/// 修改紀(jì)錄
///
/// 2016-10-31 版本:1.0 宋彪 創(chuàng)建文件。
///
/// <author>
/// <name>宋彪</name>
/// <date>2016-10-31</date>
/// </author>
/// </summary>
public class ApiResultAttribute : ActionFilterAttribute
{
/// <summary>
/// 重寫回傳的處理
/// </summary>
/// <param name="actionExecutedContext"></param>
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
// 快件跟蹤接口傳的是format,不用走這里
if (actionExecutedContext.Request.Properties.ContainsKey("format"))
{
// 若發(fā)生例外則不在這邊處理 在異常中處理 ApiErrorHandleAttribute
if (actionExecutedContext.Exception != null)
return;
base.OnActionExecuted(actionExecutedContext);
var result = new ApiResultModel();
// 取得由 API 返回的狀態(tài)碼
result.Status = actionExecutedContext.ActionContext.Response.StatusCode;
// 取得由 API 返回的資料
result.Data = actionExecutedContext.ActionContext.Response.Content.ReadAsAsync<object>().Result;
// 重新封裝回傳格式
actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(result.Status, result);
}
}
}
4、全局異常處理
using DotNet.Utilities;
using DotNet.Tracking.API.Common;
using DotNet.Tracking.API.Controllers;
using DotNet.Tracking.API.Models;
/// <summary>
/// ApiErrorHandleAttribute
/// 全局異常處理
///
/// 修改紀(jì)錄
///
/// 2016-10-31 版本:1.0 宋彪 創(chuàng)建文件。
///
/// <author>
/// <name>宋彪</name>
/// <date>2016-10-31</date>
/// </author>
/// </summary>
public class ApiErrorHandleAttribute : System.Web.Http.Filters.ExceptionFilterAttribute
{
/// <summary>
/// 異常統(tǒng)一處理
/// </summary>
/// <param name="actionExecutedContext"></param>
public override void OnException(System.Web.Http.Filters.HttpActionExecutedContext actionExecutedContext)
{
base.OnException(actionExecutedContext);
// 取得發(fā)生例外時(shí)的錯(cuò)誤訊息
var errorMessage = actionExecutedContext.Exception.Message;
// 異常記錄
string parameters = APIOperateContext.GetRequestParameters();
NLogHelper.Trace(actionExecutedContext.Exception, BaseSystemInfo.SystemCode + " ApiErrorHandleAttribute OnException 完整的請求地址及參數(shù) : " + parameters);
// 2016-11-01 加入異常郵件提醒
NLogHelper.InfoMail(actionExecutedContext.Exception, BaseSystemInfo.SystemCode + " ApiErrorHandleAttribute OnException 完整的請求地址及參數(shù) : " + parameters);
var result = new ApiResultModel()
{
Status = HttpStatusCode.BadRequest,
ErrorMessage = errorMessage
};
// 重新打包回傳的訊息
actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(result.Status, result);
}
}
5、接口操作的上下文
using DotNet.Business;
using DotNet.Model;
using DotNet.Utilities;
/// <summary>
/// APIOperateContext
/// 接口操作的上下文
/// 跟上下文有關(guān)的一些通用的東西放在這里處理
///
/// 修改紀(jì)錄
///
/// 2016-10-31 版本:1.0 宋彪 創(chuàng)建文件。
///
/// <author>
/// <name>宋彪</name>
/// <date>2016-10-31</date>
/// </author>
/// </summary>
public class APIOperateContext
{
/// <summary>
/// 獲取當(dāng)前 操作上下文 (為每個(gè)處理瀏覽器請求的服務(wù)器線程 單獨(dú)創(chuàng)建 操作上下文)
/// </summary>
public static APIOperateContext Current
{
get
{
APIOperateContext oContext = CallContext.GetData(typeof(APIOperateContext).Name) as APIOperateContext;
if (oContext == null)
{
oContext = new APIOperateContext();
CallContext.SetData(typeof(APIOperateContext).Name, oContext);
}
return oContext;
}
}
#region Http上下文 及 相關(guān)屬性
/// <summary>
/// Http上下文
/// </summary>
public HttpContext ContextHttp
{
get
{
return HttpContext.Current;
}
}
/// <summary>
/// 輸出對象
/// </summary>
public HttpResponse Response
{
get
{
return ContextHttp.Response;
}
}
/// <summary>
/// 請求對象
/// </summary>
public HttpRequest Request
{
get
{
return ContextHttp.Request;
}
}
/// <summary>
/// Session對象
/// </summary>
System.Web.SessionState.HttpSessionState Session
{
get
{
return ContextHttp.Session;
}
}
#endregion
/// <summary>
/// 獲取全部請求參數(shù),get和post的 簡化版
/// </summary>
public static string GetRequestParameters()
{
string query = HttpContext.Current.Request.Url.Query;
NameValueCollection nvc;
string baseUrl;
ParseUrl(query, out baseUrl, out nvc);
List<string> list = new List<string>() { };
foreach (var key in nvc.AllKeys)
{
list.Add(key + "=" + nvc[key]);
}
var form = HttpContext.Current.Request.Form;
foreach (var key in form.AllKeys)
{
list.Add(key + "=" + form[key]);
}
string result = HttpContext.Current.Request.Url.AbsoluteUri + "?" + string.Join("&", list);
return result;
}
/// <summary>
/// 分析 url 字符串中的參數(shù)信息
/// 針對get請求的
/// </summary>
/// <param name="url">輸入的 URL</param>
/// <param name="baseUrl">輸出 URL 的基礎(chǔ)部分</param>
/// <param name="nvc">輸出分析后得到的 (參數(shù)名,參數(shù)值) 的集合</param>
public static void ParseUrl(string url, out string baseUrl, out NameValueCollection nvc)
{
if (url == null)
{
throw new ArgumentNullException("url");
}
nvc = new NameValueCollection();
baseUrl = "";
if (url == "")
{
return;
}
int questionMarkIndex = url.IndexOf('?');
if (questionMarkIndex == -1)
{
baseUrl = url;
return;
}
baseUrl = url.Substring(0, questionMarkIndex);
if (questionMarkIndex == url.Length - 1)
{
return;
}
string ps = url.Substring(questionMarkIndex + 1);
// 開始分析參數(shù)對
Regex re = new Regex(@"(^|&)?(\w+)=([^&]+)(&|$)?", RegexOptions.Compiled);
MatchCollection mc = re.Matches(ps);
foreach (Match m in mc)
{
nvc.Add(m.Result("$2").ToLower(), m.Result("$3"));
}
}
/// <summary>
/// 系統(tǒng)編號(hào)
/// </summary>
public string SystemCode
{
get
{
return Request["systemCode"] ?? "Base";
}
}
/// <summary>
/// 權(quán)限編號(hào)
/// </summary>
public string PermissionCode
{
get
{
return Request["permissionCode"];
}
}
/// <summary>
/// 訪問接口的應(yīng)用傳來AppKey
/// </summary>
public string AppKey
{
get
{
return Request["appKey"];
}
}
/// <summary>
/// 訪問接口的應(yīng)用傳來AppSecret
/// </summary>
public string AppSecret
{
get
{
return Request["appSecret"];
}
}
private BaseUserInfo _userInfo = null;
/// <summary>
/// 獲取當(dāng)前用戶
/// 通過接口AppKey和AppSecret獲取的用戶
/// </summary>
/// <returns></returns>
public BaseUserInfo UserInfo
{
get
{
BaseUserInfo userInfo = null;
BaseUserEntity userEntity = BaseUserManager.GetObjectByCodeByCache(AppKey);
if (userEntity != null)
{
if (BaseServicesLicenseManager.CheckServiceByCache(userEntity.Id, AppSecret))
{
userInfo = new BaseUserInfo();
userInfo.Id = userEntity.Id;
userInfo.RealName = userEntity.RealName;
userInfo.UserName = userEntity.UserName;
userInfo.IPAddress = Utilities.GetIPAddress(true);
}
}
return userInfo;
}
}
#region 業(yè)務(wù)庫連接
/// <summary>
/// 業(yè)務(wù)庫連接
/// </summary>
public static IDbHelper BusinessDbHelper
{
get
{
return DbHelperFactory.GetHelper(BaseSystemInfo.BusinessDbType, BaseSystemInfo.BusinessDbConnection);
}
}
#endregion
#region 用戶中心庫連接
/// <summary>
/// 用戶中心庫連接
/// </summary>
public static IDbHelper UserCenterDbHelper
{
get
{
return DbHelperFactory.GetHelper(BaseSystemInfo.UserCenterDbType, BaseSystemInfo.UserCenterDbConnection);
}
}
#endregion
}
7、統(tǒng)一回傳格式實(shí)體
/// <summary>
/// ApiResultModel
/// 統(tǒng)一回傳格式實(shí)體
///
/// 修改紀(jì)錄
///
/// 2016-10-31 版本:1.0 宋彪 創(chuàng)建文件。
///
/// <author>
/// <name>宋彪</name>
/// <date>2016-10-31</date>
/// </author>
/// </summary>
public class ApiResultModel
{
public HttpStatusCode Status { get; set; }
//public JsonResult<T> Data { get; set; }
public object Data { get; set; }
public string ErrorMessage { get; set; }
}
8、留言相關(guān)接口
/// <summary>
/// MessageBookController
/// 留言相關(guān)接口
///
/// 修改紀(jì)錄
///
/// 2016-10-31 版本:1.0 宋彪 創(chuàng)建文件。
///
/// <author>
/// <name>宋彪</name>
/// <date>2016-10-31</date>
/// </author>
/// </summary>
[ApiAuthFilter]
public class CustomerMessageController : ApiController
{
/// <summary>
/// 保存單號(hào)留言信息
/// </summary>
/// <param name="messageBook"></param>
/// <returns></returns>
[HttpPost]
//[AllowAnonymous] 不需要驗(yàn)證的就加這個(gè)標(biāo)簽
public IHttpActionResult Add([FromBody]MsgbookCusEntity messageBook)
{
BaseResult baseResult = new BaseResult();
if (string.IsNullOrWhiteSpace(messageBook.SystemFrom))
{
baseResult.Status = false;
baseResult.StatusMessage = "SystemFrom參數(shù)不可為空";
}
else
{
try
{
MsgbookCusManager manager = new MsgbookCusManager(APIOperateContext.BusinessDbHelper, APIOperateContext.Current.UserInfo);
MsgbookCusEntity model = new MsgbookCusEntity();
model.Id = Guid.NewGuid().ToString("N");
model.Message = messageBook.Message;
model.SendEmail = messageBook.SendEmail;
model.SendTelephone = messageBook.SendTelephone;
model.Message = messageBook.Message;
model.BillCode = messageBook.BillCode;
model.SystemFrom = messageBook.SystemFrom;
model.DeletionStateCode = 0;
manager.Add(model, false, false);
baseResult.Status = true;
baseResult.StatusMessage = "添加成功。";
}
catch (Exception ex)
{
NLogHelper.Warn(ex, "CustomerMessageController AddBillMessage 異常");
baseResult.Status = false;
baseResult.StatusMessage = "異常:" + ex.Message;
}
}
return Ok(baseResult);
}
/// <summary>
/// 獲取某個(gè)單號(hào)的留言
/// </summary>
/// <param name="billCode"></param>
/// <returns></returns>
[HttpGet]
public IHttpActionResult GetList(string billCode)
{
JsonResult<List<MsgbookCusEntity>> jsonResult = new JsonResult<List<MsgbookCusEntity>>();
try
{
MsgbookCusManager manager = new MsgbookCusManager(APIOperateContext.BusinessDbHelper, APIOperateContext.Current.UserInfo);
List<MsgbookCusEntity> list = new List<MsgbookCusEntity>();
list = manager.GetList<MsgbookCusEntity>(new KeyValuePair<string, object>(MsgbookCusEntity.FieldBillCode, billCode)
, new KeyValuePair<string, object>(MsgbookCusEntity.FieldDeletionStateCode, 0));
jsonResult.Status = true;
jsonResult.RecordCount = list.Count;
jsonResult.Data = list;
jsonResult.StatusMessage = "獲取成功";
}
catch (Exception ex)
{
NLogHelper.Warn(ex, "CustomerMessageController AddBillMessage 異常");
jsonResult.Status = false;
jsonResult.StatusMessage = "異常:" + ex.Message;
}
return Ok(jsonResult);
}
}
9、接口調(diào)用方法
/// <summary>
/// 測試留言接口調(diào)用
/// </summary>
/// <returns></returns>
public ActionResult AddCustomerMessage()
{
string url = "http://192.168.1.88:808/api/CustomerMessage/Add?";
WebClient webClient = new WebClient();
NameValueCollection postValues = new NameValueCollection();
postValues.Add("Message", "填寫您的留言內(nèi)容吧");
postValues.Add("SendEmail", "youemail@qq.com");
postValues.Add("SendTelephone", "021-60375335");
postValues.Add("Code", "661137858");
postValues.Add("AppKey", "wssavbcn");
postValues.Add("AppSecret", "350e66b1e6564b0a817163erwwwwe8");
postValues.Add("SystemFrom", "官網(wǎng)");
byte[] responseArray = webClient.UploadValues(url, postValues);
string response = Encoding.UTF8.GetString(responseArray);
return Content(response);
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Asp.Net程序目錄下文件夾或文件操作導(dǎo)致Session失效的解決方案
這篇文章主要介紹了Asp.Net程序目錄下文件夾或文件操作導(dǎo)致Session失效的解決方案,需要的朋友可以參考下2017-06-06
.Net Core配置與自動(dòng)更新的實(shí)現(xiàn)方法
下面小編就為大家分享一篇.Net Core配置與自動(dòng)更新的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12
.NET Framework集成Quartz的實(shí)現(xiàn)示例
本文主要介紹了.NET Framework集成Quartz的實(shí)現(xiàn)示例,Quartz 主要用于定時(shí)執(zhí)行任務(wù)方面,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-03-03
ASP.NET Core 2.0 支付寶掃碼支付的實(shí)現(xiàn)代碼
這篇文章主要介紹了ASP.NET Core 2.0 支付寶掃碼支付的實(shí)現(xiàn)代碼,需要的朋友可以參考下2017-10-10
Asp.net SignalR創(chuàng)建實(shí)時(shí)聊天應(yīng)用程序
這篇文章主要介紹了Asp.net SignalR創(chuàng)建實(shí)時(shí)聊天應(yīng)用程序,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11
詳解ASP.NET Core3.0 配置的Options模式
這篇文章主要介紹了詳解ASP.NET Core3.0 配置的Options模式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08

