当前位置: 移动技术网 > IT编程>开发语言>.net > ASP.NET MVC API 接口验证的示例代码

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

2017年10月21日  | 移动技术网IT编程  | 我要评论

吉尔克尼斯,夫妇乐园小说,猪刚鬣 陈炳强

项目中有一个留言消息接口,接收其他系统的留言和展示留言,参考了网上的一些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);
    }

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网