ASP.NET MVC API 接口验证
项目中有一个留言消息接口,接收其他系统的留言和展示留言,参考了网上的一些API验证方法,发现使用通用权限管理系统提供的验证方法最完美(http://www.cnblogs.com/jirigala/p/5506022.html)。
下面将实现的完整思路共享
1、WebApiConfig全局处理
/// <summary>
/// WebApiConfig
/// 路由基础配置。
///
///
/// 修改记录
///
/// 2016.11.01 版本:2.0 宋彪 对日期格式进行统一处理。
/// 2016.10.30 版本:2.0 宋彪 解决json序列化时的循环引用问题。
/// 2016.10.28 版本:2.0 宋彪 回传响应格式 $format 支持。
/// 2016.09.01 版本:1.0 宋彪 创建。
///
/// 版本:1.0
///
/// <author>
/// <name>宋彪</name>
/// <date>2016.09.01</date>
/// </author>
/// </summary>
public static class WebApiConfig
{
/// <summary>
/// 注册全局配置服务
/// </summary>
/// <param name="config"></param>
public static void Register(HttpConfiguration config)
{
// Web API configuration and services //强制https访问
//config.Filters.Add(new ForceHttpsAttribute());
// 统一回传格式
config.Filters.Add(new ApiResultAttribute());
// 发生异常时处理
config.Filters.Add(new ApiErrorHandleAttribute());
// ToKen身份验证过滤器 更方便 不需要在这里了 具有改标签的就会自动检查
//config.Filters.Add(new ApiAuthFilterAttribute());
// 解决json序列化时的循环引用问题
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
//对日期格式进行统一处理
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,便可以指定响应格式
config.Formatters.XmlFormatter.AddQueryStringMapping("$format", "xml", "application/xml");
config.Formatters.JsonFormatter.AddQueryStringMapping("$format", "json", "application/json");
}
}
2、身份验证过滤器
using DotNet.Business;
using DotNet.Utilities;
using DotNet.Tracking.API.Common; /// <summary>
/// ApiAuthFilterAttribute
/// 身份验证过滤器,具有ApiAuthFilterAttribute标签属性的方法会自动检查
///
///
/// 修改纪录
///
/// 2016-10-11 版本:1.0 SongBiao 创建文件。
///
/// <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>
/// 未授权时的提示信息
/// </summary>
private const string UnauthorizedMessage = "请求未授权,拒绝访问。"; /// <summary>
/// 权限进入
/// </summary>
/// <param name="actionContext"></param>
public override void OnAuthorization(HttpActionContext actionContext)
{
base.OnAuthorization(actionContext);
// 允许匿名访问
if (actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Count > )
{
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))
{
//未验证(登录)的用户, 而且是非匿名访问,则转向登录页面
//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, , , systemCode, permissionCode);
if (!result.Status)
{
var response = actionContext.Response = actionContext.Response?? new HttpResponseMessage();
response.Content = new StringContent(result.ToJson(), Encoding.UTF8, "application/json");
}
} }
}
3、统一回传格式
/// <summary>
/// ApiResultAttribute
/// 统一回传格式
///
/// 修改纪录
///
/// 2016-10-31 版本:1.0 宋彪 创建文件。
///
/// <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"))
{
// 若发生例外则不在这边处理 在异常中处理 ApiErrorHandleAttribute
if (actionExecutedContext.Exception != null)
return;
base.OnActionExecuted(actionExecutedContext);
var result = new ApiResultModel();
// 取得由 API 返回的状态码
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
/// 全局异常处理
///
/// 修改纪录
///
/// 2016-10-31 版本:1.0 宋彪 创建文件。
///
/// <author>
/// <name>宋彪</name>
/// <date>2016-10-31</date>
/// </author>
/// </summary> public class ApiErrorHandleAttribute : System.Web.Http.Filters.ExceptionFilterAttribute
{
/// <summary>
/// 异常统一处理
/// </summary>
/// <param name="actionExecutedContext"></param>
public override void OnException(System.Web.Http.Filters.HttpActionExecutedContext actionExecutedContext)
{
base.OnException(actionExecutedContext);
// 取得发生例外时的错误讯息
var errorMessage = actionExecutedContext.Exception.Message; // 异常记录
string parameters = APIOperateContext.GetRequestParameters();
NLogHelper.Trace(actionExecutedContext.Exception, BaseSystemInfo.SystemCode + " ApiErrorHandleAttribute OnException 完整的请求地址及参数 : " + parameters);
// 2016-11-01 加入异常邮件提醒
NLogHelper.InfoMail(actionExecutedContext.Exception, BaseSystemInfo.SystemCode + " ApiErrorHandleAttribute OnException 完整的请求地址及参数 : " + 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
/// 接口操作的上下文
/// 跟上下文有关的一些通用的东西放在这里处理
///
/// 修改纪录
///
/// 2016-10-31 版本:1.0 宋彪 创建文件。
///
/// <author>
/// <name>宋彪</name>
/// <date>2016-10-31</date>
/// </author>
/// </summary>
public class APIOperateContext
{
/// <summary>
/// 获取当前 操作上下文 (为每个处理浏览器请求的服务器线程 单独创建 操作上下文)
/// </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上下文 及 相关属性
/// <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>
/// 获取全部请求参数,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 字符串中的参数信息
/// 针对get请求的
/// </summary>
/// <param name="url">输入的 URL</param>
/// <param name="baseUrl">输出 URL 的基础部分</param>
/// <param name="nvc">输出分析后得到的 (参数名,参数值) 的集合</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 == -)
{
baseUrl = url;
return;
}
baseUrl = url.Substring(, questionMarkIndex);
if (questionMarkIndex == url.Length - )
{
return;
}
string ps = url.Substring(questionMarkIndex + );
// 开始分析参数对
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>
/// 系统编号
/// </summary>
public string SystemCode
{
get
{
return Request["systemCode"] ?? "Base";
}
} /// <summary>
/// 权限编号
/// </summary>
public string PermissionCode
{
get
{
return Request["permissionCode"];
}
} /// <summary>
/// 访问接口的应用传来AppKey
/// </summary>
public string AppKey
{
get
{
return Request["appKey"];
}
} /// <summary>
/// 访问接口的应用传来AppSecret
/// </summary>
public string AppSecret
{
get
{
return Request["appSecret"];
}
} private BaseUserInfo _userInfo = null;
/// <summary>
/// 获取当前用户
/// 通过接口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 业务库连接
/// <summary>
/// 业务库连接
/// </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、统一回传格式实体
/// <summary>
/// ApiResultModel
/// 统一回传格式实体
///
/// 修改纪录
///
/// 2016-10-31 版本:1.0 宋彪 创建文件。
///
/// <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、留言相关接口
/// <summary>
/// MessageBookController
/// 留言相关接口
///
/// 修改纪录
///
/// 2016-10-31 版本:1.0 宋彪 创建文件。
///
/// <author>
/// <name>宋彪</name>
/// <date>2016-10-31</date>
/// </author>
/// </summary>
[ApiAuthFilter]
public class CustomerMessageController : ApiController
{
/// <summary>
/// 保存单号留言信息
/// </summary>
/// <param name="messageBook"></param>
/// <returns></returns>
[HttpPost]
//[AllowAnonymous] 不需要验证的就加这个标签
public IHttpActionResult Add([FromBody]MsgbookCusEntity messageBook)
{
BaseResult baseResult = new BaseResult();
if (string.IsNullOrWhiteSpace(messageBook.SystemFrom))
{
baseResult.Status = false;
baseResult.StatusMessage = "SystemFrom参数不可为空";
}
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 = ;
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>
/// 获取某个单号的留言
/// </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, )); 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、接口调用方法
/// <summary>
/// 测试留言接口调用
/// </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", "填写您的留言内容吧");
postValues.Add("SendEmail", "youemail@qq.com");
postValues.Add("SendTelephone", "021-60375335");
postValues.Add("Code", "");
postValues.Add("AppKey", "wssavbcn");
postValues.Add("AppSecret", "350e66b1e6564b0a817163erwwwwe8");
postValues.Add("SystemFrom", "官网"); byte[] responseArray = webClient.UploadValues(url, postValues);
string response = Encoding.UTF8.GetString(responseArray); return Content(response);
}
ASP.NET MVC API 接口验证的更多相关文章
- asp.net mvc ,asp.net mvc api 中使用全局过滤器进行异常捕获记录
MVC下的全局异常过滤器注册方式如下:标红为asp.net mvc ,asp.net mvc api 注册全局异常过滤器的不同之处 using SuperManCore; using System. ...
- 一百元的智能家居——Asp.Net Mvc Api+讯飞语音+Android+Arduino
大半夜的,先说些废话提提神 如今智能家居已经不再停留在概念阶段,高大上的科技公司都已经推出了自己的部分或全套的智能家居解决方案,不过就目前的现状而言,大多还停留在展厅阶段,还没有广泛的推广起来,有人说 ...
- ASP.NET Web API 接口执行时间监控
软件产品常常会出现这样的情况:产品性能因某些无法预料的瓶颈而受到干扰,导致程序的处理效率降低,性能得不到充分的发挥.如何快速有效地找到软件产品的性能瓶颈,则是我们感兴趣的内容之一. 在本文中,我将解释 ...
- ASP.NET MVC API 路由生成规则
我们都知道调用ASP.NET MVC的某些API函数(诸如:Url.Action.RedirectToAction等)可以生成URL,ASP.NET MVC会根据调用API函数时传入的参数去匹配系统定 ...
- Asp.Net Web Api 接口,拥抱支持跨域访问。
如何让你的 Asp.Net Web Api 接口,拥抱支持跨域访问. 由于 web api 项目通常是被做成了一个独立站点,来提供数据,在做web api 项目的时候,不免前端会遇到跨域访问接口的问题 ...
- Asp.Net Web Api 接口
如何让你的 Asp.Net Web Api 接口,拥抱支持跨域访问. 由于 web api 项目通常是被做成了一个独立站点,来提供数据,在做web api 项目的时候,不免前端会遇到跨域访问接口的 ...
- asp.net mvc+httpclient+asp.net mvc api入门篇
第一步:创建一个ASP.NET MVC API项目 第二步:在api项目里面创建一个类 public class Student { public int Id { get; set; } publi ...
- ASP.NET MVC API与JS进行POST请求时传递参数 -CHPowerljp原创
在API前添加 [HttpPost] 表示只允许POST方式请求 [HttpPost] public IHttpActionResult Get_BIGDATA([FromBody]Datas ...
- ASP.NET MVC WebApi接口授权验证
对于很任何多开发者来说,不管是使用任何一种框架,或者是使用任何一种语言,都要使用面向接口编程.使用面向接口编程的时候,那么就会有很多的权限验证,用户验证等等. 特别是对于一些系统来说,别人想要对接你的 ...
随机推荐
- [T-ARA][느낌 아니까][懂得那份感觉]
歌词来源:http://music.163.com/#/song?id=27808771 作曲 : 박덕상/박현중 [作曲 : p/bag-ddeog-ssang-/p/ba-Kyeon-c/jung ...
- 关于Python的面试题
Python语言特性 1 Python的函数参数传递 看两个例子: a = 1 def fun(a): a = 2 fun(a) print a # 1 a = [] def fun(a): a.ap ...
- [redis] 几种redis数据导出导入方式
环境说明: 172.20.0.1 redis源实例 172.20.0.2 redis目标实例 172.20.0.3 任意linux系统 一.redis-dump方式 1.安装redis-dump工具 ...
- Scrum立会报告+燃尽图(Final阶段第三次)
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2481 项目地址:https://coding.net/u/wuyy694 ...
- Beta周王者荣耀交流协会第一次Scrum会议
1.立会照片 成员王超,高远博,冉华,王磊,王玉玲,任思佳,袁玥全部到齐. master:王超 2.时间跨度: 2017年11月10日 15:10 — 15:50 ,总计40分钟. 3.地 点: 一食 ...
- hadoop在章鱼大数据平台下的安装与配置
本次所用的软件版本: ubuntu :14.04 Hadoop:hadoop-2.6.0-cdh5.4.5 jdk:jdk-7u75-linux-x64 Hive: Hbase: 一.配置基本环境 1 ...
- TeamWork#3,Week5,Scrum Meeting 11.6, 11.7, 11.11, 11.12
11.6:到目前为止基本已完成相关知识的学习,各方面工作都开始进行,一开始进行比较慢. 11.7:项目遇到困难,需要补充相关知识,进度慢了下来. 11.11:各方面工作进展比较顺利,没有什么大问题. ...
- [BUAA软工]第0次个人作业
[BUAA软工]第0次个人作业 本次作业所属课程 : 2019BUAA软件工程 本次作业要求: 第0次个人作业 我在本课程的目标: 熟悉软件工程流程,规范开发习惯 本次作业的帮助: 熟悉课程流程 Pa ...
- 实验五 Java网络编程及安全 实验报告 20135232王玥
北京电子科技学院(BESTI) 实 验 报 告 课程:Java程序与设计 班级:1352 姓名:王玥 学号:20135232 成绩: 指导 ...
- 现代软件工程构建之法 前五章阅读感想&困惑
第一章 第一节 新时代中国的IT产业市场规则不规范,书中提到社会上有个别软件公司的软件一定要卸载别家公司的软件才能运行,我这里感到疑惑---————是不是说如果 一间软件公司他能做出一个像微软操作系统 ...