查看: 1738|回复: 0

[ASP.NET教程] ASP.NET MVC API 接口验证的示例代码

发表于 2018-1-3 08:00:01

项目中有一个留言消息接口,接收其他系统的留言和展示留言,参考了网上的一些API验证方法,发现使用通用权限管理系统提供的验证方法最完美。

下面将实现的完整思路共享

1、WebApiConfig全局处理

  1. /// <summary>
  2. /// WebApiConfig
  3. /// 路由基础配置。
  4. ///
  5. ///
  6. /// 修改记录
  7. ///
  8. /// 2016.11.01 版本:2.0 宋彪 对日期格式进行统一处理。
  9. /// 2016.10.30 版本:2.0 宋彪 解决json序列化时的循环引用问题。
  10. /// 2016.10.28 版本:2.0 宋彪 回传响应格式 $format 支持。
  11. /// 2016.09.01 版本:1.0 宋彪 创建。
  12. ///
  13. /// 版本:1.0
  14. ///
  15. /// <author>
  16. /// <name>宋彪</name>
  17. /// <date>2016.09.01</date>
  18. /// </author>
  19. /// </summary>
  20. public static class WebApiConfig
  21. {
  22. /// <summary>
  23. /// 注册全局配置服务
  24. /// </summary>
  25. /// <param name="config"></param>
  26. public static void Register(HttpConfiguration config)
  27. {
  28. // Web API configuration and services
  29. //强制https访问
  30. //config.Filters.Add(new ForceHttpsAttribute());
  31. // 统一回传格式
  32. config.Filters.Add(new ApiResultAttribute());
  33. // 发生异常时处理
  34. config.Filters.Add(new ApiErrorHandleAttribute());
  35. // ToKen身份验证过滤器 更方便 不需要在这里了 具有改标签的就会自动检查
  36. //config.Filters.Add(new ApiAuthFilterAttribute());
  37. // 解决json序列化时的循环引用问题
  38. config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
  39. //对日期格式进行统一处理
  40. config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(
  41. new IsoDateTimeConverter()
  42. {
  43. DateTimeFormat = "yyyy-MM-dd hh:mm:ss"
  44. }
  45. );
  46. // Web API routes 路由
  47. config.MapHttpAttributeRoutes();
  48. config.Routes.MapHttpRoute(
  49. name: "DefaultApi",
  50. routeTemplate: "api/{controller}/{action}/{id}",
  51. defaults: new { id = RouteParameter.Optional }
  52. );
  53. // 干掉XML序列化器
  54. //config.Formatters.Remove(config.Formatters.XmlFormatter);
  55. //在请求的Url加上 ?$format=xml,便可以指定响应格式
  56. config.Formatters.XmlFormatter.AddQueryStringMapping("$format", "xml", "application/xml");
  57. config.Formatters.JsonFormatter.AddQueryStringMapping("$format", "json", "application/json");
  58. }
  59. }
复制代码

2、身份验证过滤器

  1. using DotNet.Business;
  2. using DotNet.Utilities;
  3. using DotNet.Tracking.API.Common;
  4. /// <summary>
  5. /// ApiAuthFilterAttribute
  6. /// 身份验证过滤器,具有ApiAuthFilterAttribute标签属性的方法会自动检查
  7. ///
  8. ///
  9. /// 修改纪录
  10. ///
  11. /// 2016-10-11 版本:1.0 SongBiao 创建文件。
  12. ///
  13. /// <author>
  14. /// <name>SongBiao</name>
  15. /// <date>2016-10-11</date>
  16. /// </author>
  17. /// </summary>
  18. [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
  19. public class ApiAuthFilterAttribute : AuthorizationFilterAttribute
  20. {
  21. /// <summary>
  22. /// 未授权时的提示信息
  23. /// </summary>
  24. private const string UnauthorizedMessage = "请求未授权,拒绝访问。";
  25. /// <summary>
  26. /// 权限进入
  27. /// </summary>
  28. /// <param name="actionContext"></param>
  29. public override void OnAuthorization(HttpActionContext actionContext)
  30. {
  31. base.OnAuthorization(actionContext);
  32. // 允许匿名访问
  33. if (actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Count > 0)
  34. {
  35. return;
  36. }
  37. string systemCode = APIOperateContext.Current.SystemCode;
  38. string permissionCode = APIOperateContext.Current.PermissionCode;
  39. string appKey = APIOperateContext.Current.AppKey;
  40. string appSecret = APIOperateContext.Current.AppSecret;
  41. if (string.IsNullOrWhiteSpace(appKey) || string.IsNullOrWhiteSpace(appSecret))
  42. {
  43. //未验证(登录)的用户, 而且是非匿名访问,则转向登录页面
  44. //actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
  45. //actionContext.Response.Content = new StringContent("<p>Unauthorized</p>", Encoding.UTF8, "text/html");
  46. var response = actionContext.Response= actionContext.Response?? new HttpResponseMessage();
  47. response.StatusCode = HttpStatusCode.Unauthorized;
  48. BaseResult result = new BaseResult
  49. {
  50. Status = false,
  51. StatusMessage = UnauthorizedMessage
  52. };
  53. response.Content = new StringContent(result.ToJson(), Encoding.UTF8, "application/json");
  54. }
  55. else
  56. {
  57. // 检查 AppKey 和 AppSecret
  58. BaseResult result = BaseServicesLicenseManager.CheckService(appKey, appSecret, false, 0, 0, systemCode, permissionCode);
  59. if (!result.Status)
  60. {
  61. var response = actionContext.Response = actionContext.Response?? new HttpResponseMessage();
  62. response.Content = new StringContent(result.ToJson(), Encoding.UTF8, "application/json");
  63. }
  64. }
  65. }
  66. }
复制代码

3、统一回传格式

  1. /// <summary>
  2. /// ApiResultAttribute
  3. /// 统一回传格式
  4. ///
  5. /// 修改纪录
  6. ///
  7. /// 2016-10-31 版本:1.0 宋彪 创建文件。
  8. ///
  9. /// <author>
  10. /// <name>宋彪</name>
  11. /// <date>2016-10-31</date>
  12. /// </author>
  13. /// </summary>
  14. public class ApiResultAttribute : ActionFilterAttribute
  15. {
  16. /// <summary>
  17. /// 重写回传的处理
  18. /// </summary>
  19. /// <param name="actionExecutedContext"></param>
  20. public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
  21. {
  22. // 快件跟踪接口传的是format,不用走这里
  23. if (actionExecutedContext.Request.Properties.ContainsKey("format"))
  24. {
  25. // 若发生例外则不在这边处理 在异常中处理 ApiErrorHandleAttribute
  26. if (actionExecutedContext.Exception != null)
  27. return;
  28. base.OnActionExecuted(actionExecutedContext);
  29. var result = new ApiResultModel();
  30. // 取得由 API 返回的状态码
  31. result.Status = actionExecutedContext.ActionContext.Response.StatusCode;
  32. // 取得由 API 返回的资料
  33. result.Data = actionExecutedContext.ActionContext.Response.Content.ReadAsAsync<object>().Result;
  34. // 重新封装回传格式
  35. actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(result.Status, result);
  36. }
  37. }
  38. }
复制代码

4、全局异常处理

  1. using DotNet.Utilities;
  2. using DotNet.Tracking.API.Common;
  3. using DotNet.Tracking.API.Controllers;
  4. using DotNet.Tracking.API.Models;
  5. /// <summary>
  6. /// ApiErrorHandleAttribute
  7. /// 全局异常处理
  8. ///
  9. /// 修改纪录
  10. ///
  11. /// 2016-10-31 版本:1.0 宋彪 创建文件。
  12. ///
  13. /// <author>
  14. /// <name>宋彪</name>
  15. /// <date>2016-10-31</date>
  16. /// </author>
  17. /// </summary>
  18. public class ApiErrorHandleAttribute : System.Web.Http.Filters.ExceptionFilterAttribute
  19. {
  20. /// <summary>
  21. /// 异常统一处理
  22. /// </summary>
  23. /// <param name="actionExecutedContext"></param>
  24. public override void OnException(System.Web.Http.Filters.HttpActionExecutedContext actionExecutedContext)
  25. {
  26. base.OnException(actionExecutedContext);
  27. // 取得发生例外时的错误讯息
  28. var errorMessage = actionExecutedContext.Exception.Message;
  29. // 异常记录
  30. string parameters = APIOperateContext.GetRequestParameters();
  31. NLogHelper.Trace(actionExecutedContext.Exception, BaseSystemInfo.SystemCode + " ApiErrorHandleAttribute OnException 完整的请求地址及参数 : " + parameters);
  32. // 2016-11-01 加入异常邮件提醒
  33. NLogHelper.InfoMail(actionExecutedContext.Exception, BaseSystemInfo.SystemCode + " ApiErrorHandleAttribute OnException 完整的请求地址及参数 : " + parameters);
  34. var result = new ApiResultModel()
  35. {
  36. Status = HttpStatusCode.BadRequest,
  37. ErrorMessage = errorMessage
  38. };
  39. // 重新打包回传的讯息
  40. actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(result.Status, result);
  41. }
  42. }
复制代码

5、接口操作的上下文

  1. using DotNet.Business;
  2. using DotNet.Model;
  3. using DotNet.Utilities;
  4. /// <summary>
  5. /// APIOperateContext
  6. /// 接口操作的上下文
  7. /// 跟上下文有关的一些通用的东西放在这里处理
  8. ///
  9. /// 修改纪录
  10. ///
  11. /// 2016-10-31 版本:1.0 宋彪 创建文件。
  12. ///
  13. /// <author>
  14. /// <name>宋彪</name>
  15. /// <date>2016-10-31</date>
  16. /// </author>
  17. /// </summary>
  18. public class APIOperateContext
  19. {
  20. /// <summary>
  21. /// 获取当前 操作上下文 (为每个处理浏览器请求的服务器线程 单独创建 操作上下文)
  22. /// </summary>
  23. public static APIOperateContext Current
  24. {
  25. get
  26. {
  27. APIOperateContext oContext = CallContext.GetData(typeof(APIOperateContext).Name) as APIOperateContext;
  28. if (oContext == null)
  29. {
  30. oContext = new APIOperateContext();
  31. CallContext.SetData(typeof(APIOperateContext).Name, oContext);
  32. }
  33. return oContext;
  34. }
  35. }
  36. #region Http上下文 及 相关属性
  37. /// <summary>
  38. /// Http上下文
  39. /// </summary>
  40. public HttpContext ContextHttp
  41. {
  42. get
  43. {
  44. return HttpContext.Current;
  45. }
  46. }
  47. /// <summary>
  48. /// 输出对象
  49. /// </summary>
  50. public HttpResponse Response
  51. {
  52. get
  53. {
  54. return ContextHttp.Response;
  55. }
  56. }
  57. /// <summary>
  58. /// 请求对象
  59. /// </summary>
  60. public HttpRequest Request
  61. {
  62. get
  63. {
  64. return ContextHttp.Request;
  65. }
  66. }
  67. /// <summary>
  68. /// Session对象
  69. /// </summary>
  70. System.Web.SessionState.HttpSessionState Session
  71. {
  72. get
  73. {
  74. return ContextHttp.Session;
  75. }
  76. }
  77. #endregion
  78. /// <summary>
  79. /// 获取全部请求参数,get和post的 简化版
  80. /// </summary>
  81. public static string GetRequestParameters()
  82. {
  83. string query = HttpContext.Current.Request.Url.Query;
  84. NameValueCollection nvc;
  85. string baseUrl;
  86. ParseUrl(query, out baseUrl, out nvc);
  87. List<string> list = new List<string>() { };
  88. foreach (var key in nvc.AllKeys)
  89. {
  90. list.Add(key + "=" + nvc[key]);
  91. }
  92. var form = HttpContext.Current.Request.Form;
  93. foreach (var key in form.AllKeys)
  94. {
  95. list.Add(key + "=" + form[key]);
  96. }
  97. string result = HttpContext.Current.Request.Url.AbsoluteUri + "?" + string.Join("&", list);
  98. return result;
  99. }
  100. /// <summary>
  101. /// 分析 url 字符串中的参数信息
  102. /// 针对get请求的
  103. /// </summary>
  104. /// <param name="url">输入的 URL</param>
  105. /// <param name="baseUrl">输出 URL 的基础部分</param>
  106. /// <param name="nvc">输出分析后得到的 (参数名,参数值) 的集合</param>
  107. public static void ParseUrl(string url, out string baseUrl, out NameValueCollection nvc)
  108. {
  109. if (url == null)
  110. {
  111. throw new ArgumentNullException("url");
  112. }
  113. nvc = new NameValueCollection();
  114. baseUrl = "";
  115. if (url == "")
  116. {
  117. return;
  118. }
  119. int questionMarkIndex = url.IndexOf('?');
  120. if (questionMarkIndex == -1)
  121. {
  122. baseUrl = url;
  123. return;
  124. }
  125. baseUrl = url.Substring(0, questionMarkIndex);
  126. if (questionMarkIndex == url.Length - 1)
  127. {
  128. return;
  129. }
  130. string ps = url.Substring(questionMarkIndex + 1);
  131. // 开始分析参数对
  132. Regex re = new Regex(@"(^|&)?(\w+)=([^&]+)(&|$)?", RegexOptions.Compiled);
  133. MatchCollection mc = re.Matches(ps);
  134. foreach (Match m in mc)
  135. {
  136. nvc.Add(m.Result("$2").ToLower(), m.Result("$3"));
  137. }
  138. }
  139. /// <summary>
  140. /// 系统编号
  141. /// </summary>
  142. public string SystemCode
  143. {
  144. get
  145. {
  146. return Request["systemCode"] ?? "Base";
  147. }
  148. }
  149. /// <summary>
  150. /// 权限编号
  151. /// </summary>
  152. public string PermissionCode
  153. {
  154. get
  155. {
  156. return Request["permissionCode"];
  157. }
  158. }
  159. /// <summary>
  160. /// 访问接口的应用传来AppKey
  161. /// </summary>
  162. public string AppKey
  163. {
  164. get
  165. {
  166. return Request["appKey"];
  167. }
  168. }
  169. /// <summary>
  170. /// 访问接口的应用传来AppSecret
  171. /// </summary>
  172. public string AppSecret
  173. {
  174. get
  175. {
  176. return Request["appSecret"];
  177. }
  178. }
  179. private BaseUserInfo _userInfo = null;
  180. /// <summary>
  181. /// 获取当前用户
  182. /// 通过接口AppKey和AppSecret获取的用户
  183. /// </summary>
  184. /// <returns></returns>
  185. public BaseUserInfo UserInfo
  186. {
  187. get
  188. {
  189. BaseUserInfo userInfo = null;
  190. BaseUserEntity userEntity = BaseUserManager.GetObjectByCodeByCache(AppKey);
  191. if (userEntity != null)
  192. {
  193. if (BaseServicesLicenseManager.CheckServiceByCache(userEntity.Id, AppSecret))
  194. {
  195. userInfo = new BaseUserInfo();
  196. userInfo.Id = userEntity.Id;
  197. userInfo.RealName = userEntity.RealName;
  198. userInfo.UserName = userEntity.UserName;
  199. userInfo.IPAddress = Utilities.GetIPAddress(true);
  200. }
  201. }
  202. return userInfo;
  203. }
  204. }
  205. #region 业务库连接
  206. /// <summary>
  207. /// 业务库连接
  208. /// </summary>
  209. public static IDbHelper BusinessDbHelper
  210. {
  211. get
  212. {
  213. return DbHelperFactory.GetHelper(BaseSystemInfo.BusinessDbType, BaseSystemInfo.BusinessDbConnection);
  214. }
  215. }
  216. #endregion
  217. #region 用户中心库连接
  218. /// <summary>
  219. /// 用户中心库连接
  220. /// </summary>
  221. public static IDbHelper UserCenterDbHelper
  222. {
  223. get
  224. {
  225. return DbHelperFactory.GetHelper(BaseSystemInfo.UserCenterDbType, BaseSystemInfo.UserCenterDbConnection);
  226. }
  227. }
  228. #endregion
  229. }
复制代码

7、统一回传格式实体

  1. /// <summary>
  2. /// ApiResultModel
  3. /// 统一回传格式实体
  4. ///
  5. /// 修改纪录
  6. ///
  7. /// 2016-10-31 版本:1.0 宋彪 创建文件。
  8. ///
  9. /// <author>
  10. /// <name>宋彪</name>
  11. /// <date>2016-10-31</date>
  12. /// </author>
  13. /// </summary>
  14. public class ApiResultModel
  15. {
  16. public HttpStatusCode Status { get; set; }
  17. //public JsonResult<T> Data { get; set; }
  18. public object Data { get; set; }
  19. public string ErrorMessage { get; set; }
  20. }
复制代码

8、留言相关接口

  1. /// <summary>
  2. /// MessageBookController
  3. /// 留言相关接口
  4. ///
  5. /// 修改纪录
  6. ///
  7. /// 2016-10-31 版本:1.0 宋彪 创建文件。
  8. ///
  9. /// <author>
  10. /// <name>宋彪</name>
  11. /// <date>2016-10-31</date>
  12. /// </author>
  13. /// </summary>
  14. [ApiAuthFilter]
  15. public class CustomerMessageController : ApiController
  16. {
  17. /// <summary>
  18. /// 保存单号留言信息
  19. /// </summary>
  20. /// <param name="messageBook"></param>
  21. /// <returns></returns>
  22. [HttpPost]
  23. //[AllowAnonymous] 不需要验证的就加这个标签
  24. public IHttpActionResult Add([FromBody]MsgbookCusEntity messageBook)
  25. {
  26. BaseResult baseResult = new BaseResult();
  27. if (string.IsNullOrWhiteSpace(messageBook.SystemFrom))
  28. {
  29. baseResult.Status = false;
  30. baseResult.StatusMessage = "SystemFrom参数不可为空";
  31. }
  32. else
  33. {
  34. try
  35. {
  36. MsgbookCusManager manager = new MsgbookCusManager(APIOperateContext.BusinessDbHelper, APIOperateContext.Current.UserInfo);
  37. MsgbookCusEntity model = new MsgbookCusEntity();
  38. model.Id = Guid.NewGuid().ToString("N");
  39. model.Message = messageBook.Message;
  40. model.SendEmail = messageBook.SendEmail;
  41. model.SendTelephone = messageBook.SendTelephone;
  42. model.Message = messageBook.Message;
  43. model.BillCode = messageBook.BillCode;
  44. model.SystemFrom = messageBook.SystemFrom;
  45. model.DeletionStateCode = 0;
  46. manager.Add(model, false, false);
  47. baseResult.Status = true;
  48. baseResult.StatusMessage = "添加成功。";
  49. }
  50. catch (Exception ex)
  51. {
  52. NLogHelper.Warn(ex, "CustomerMessageController AddBillMessage 异常");
  53. baseResult.Status = false;
  54. baseResult.StatusMessage = "异常:" + ex.Message;
  55. }
  56. }
  57. return Ok(baseResult);
  58. }
  59. /// <summary>
  60. /// 获取某个单号的留言
  61. /// </summary>
  62. /// <param name="billCode"></param>
  63. /// <returns></returns>
  64. [HttpGet]
  65. public IHttpActionResult GetList(string billCode)
  66. {
  67. JsonResult<List<MsgbookCusEntity>> jsonResult = new JsonResult<List<MsgbookCusEntity>>();
  68. try
  69. {
  70. MsgbookCusManager manager = new MsgbookCusManager(APIOperateContext.BusinessDbHelper, APIOperateContext.Current.UserInfo);
  71. List<MsgbookCusEntity> list = new List<MsgbookCusEntity>();
  72. list = manager.GetList<MsgbookCusEntity>(new KeyValuePair<string, object>(MsgbookCusEntity.FieldBillCode, billCode)
  73. , new KeyValuePair<string, object>(MsgbookCusEntity.FieldDeletionStateCode, 0));
  74. jsonResult.Status = true;
  75. jsonResult.RecordCount = list.Count;
  76. jsonResult.Data = list;
  77. jsonResult.StatusMessage = "获取成功";
  78. }
  79. catch (Exception ex)
  80. {
  81. NLogHelper.Warn(ex, "CustomerMessageController AddBillMessage 异常");
  82. jsonResult.Status = false;
  83. jsonResult.StatusMessage = "异常:" + ex.Message;
  84. }
  85. return Ok(jsonResult);
  86. }
  87. }
复制代码

9、接口调用方法

  1. /// <summary>
  2. /// 测试留言接口调用
  3. /// </summary>
  4. /// <returns></returns>
  5. public ActionResult AddCustomerMessage()
  6. {
  7. string url = "http://192.168.1.88:808/api/CustomerMessage/Add?";
  8. WebClient webClient = new WebClient();
  9. NameValueCollection postValues = new NameValueCollection();
  10. postValues.Add("Message", "填写您的留言内容吧");
  11. postValues.Add("SendEmail", "youemail@qq.com");
  12. postValues.Add("SendTelephone", "021-60375335");
  13. postValues.Add("Code", "661137858");
  14. postValues.Add("AppKey", "wssavbcn");
  15. postValues.Add("AppSecret", "350e66b1e6564b0a817163erwwwwe8");
  16. postValues.Add("SystemFrom", "官网");
  17. byte[] responseArray = webClient.UploadValues(url, postValues);
  18. string response = Encoding.UTF8.GetString(responseArray);
  19. return Content(response);
  20. }
复制代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持程序员之家。



回复

使用道具 举报