首页 > 编程 > .NET > 正文

ASP.NET MVC API 接口验证的示例代码

2024-07-10 13:32:42
字体:
来源:转载
供稿:网友

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

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

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 > 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))      {        //未验证(登录)的用户, 而且是非匿名访问,则转向登录页面         //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、统一回传格式

  /// <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 == -1)      {        baseUrl = url;        return;      }      baseUrl = url.Substring(0, questionMarkIndex);      if (questionMarkIndex == url.Length - 1)      {        return;      }      string ps = url.Substring(questionMarkIndex + 1);      // 开始分析参数对       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 = 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>    /// 获取某个单号的留言    /// </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、接口调用方法

    /// <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", "661137858");      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);    }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VeVb武林网。


注:相关教程知识阅读请移步到ASP.NET教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表