ASP.NET MVC API 接口验证的示例代码
程序员文章站
2022-07-03 19:21:13
项目中有一个留言消息接口,接收其他系统的留言和展示留言,参考了网上的一些api验证方法,发现使用通用权限管理系统提供的验证方法最完美。
下面将实现的完整思路共享
1...
项目中有一个留言消息接口,接收其他系统的留言和展示留言,参考了网上的一些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); }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: pm2 部署 node的三种方法示例
下一篇: Python知识点总结