最近在与一个IOS应用做接口对接,之前一直都没有遇到什么很大的问题,但是有一天发现可以通过软件解析app的url,然后直接通过url的拼接修改接口数据,这一下使得数据的安全性和准确性都降低了,于是就想到了url加密。

  然后在网上查了一下url的加密算法,使用比较普遍的还是Base64的加密,但是对于如何实现加密,网上的资料确不多,可能是我搜索的关键词不对。既然没有现成的参考文件,那么就只能靠自己了。因为所有的Controller都继承一个基Controller,所以比较自然的想到在基Controller中做一些操作,由于需要在执行具体的Action之前对url中的参数进行解密处理,所以联想到了做Asp.net项目时使用的IHttpModule接口,不过MVC有个更好的功能,那就是过滤器Filter,mvc总共提供了四种默认的Filter接口,IAuthorizationFilter、IActionFilter、IResultFilter和IExceptionFilter,关于这四种Filter的执行时间和使用方法网络上有很多,这里就不赘述了。下面就我的摸索过程做一个说明,也供大家参考,如果大家有更好的方法,还望不吝告知。

  要想能够解密Url的参数,首先需要获取的HttpRequest传递过来的参数。首先创建一个Filter,我暂且命名为DecodeUrlFitler,继承至ActionFilterAttribute,这个类已经继承了IActionFilter接口,它有四个抽象方法,分别是OnActionExecuted(在action执行完后执行)、OnActionExecuting(在action执行前执行)、OnResultExecuted(在view视图渲染之后执行)、OnResultExecuting(在view视图渲染之前执行)。很明显,我们需要重写OnActionExecuting方法,在action执行之前,将url中的参数进行解密。

第一步:获取Url中的查询参数

  获取查询参数后,如果你仔细观察,会发现Base64格式的参数有时是经过UrEncode的,所以为了之后能够准确的进行Base64的解码,我们需要将参数进行UrlDecode处理。

  1. public class AppActionFilter : ActionFilterAttribute
  2. {
  3.   public override void OnActionExecuting( ActionExecutingContext filterContext )
  4.   {
  5.     HttpRequestBase bases = (HttpRequestBase) filterContext.HttpContext.Request;
  6.     string url = bases.RawUrl.ToString().ToLower();
        //获取url中的参数
  7.     string queryString = bases.QueryString.ToString();
        //对获取到的参数进行UrlDecode处理
        queryString = HttpUtility.UrlDecode(queryString);
  8.   }
  9. }

获取参数和处理在博客园现在有很多文章都介绍了,在msdn中查看一下类型的方法,上面的代码就可以很容易写出来,比较困难的是如何将解析后的url参数替换之前的参数,然后跳转到相应的action中,然后将执行的结果返回到客户端。我在这个问题上摸索了好久,最终找到了比较好的一个方法,下面就来说说我摸到的几块石头。

第二步:url的跳转

第一块石头:使用RedirectResult

  一开始想到的是重新拼url,将解析出来的参数拼接成一个完整的url,获取url的路径可以使用HttpRequestBase的FilePath属性获取到路径,然后获取到domain,在加上解密的queryString就可以拼接成一条完整的url了。但是如果你查看浏览器的报文,会发现这其实是进行了一个url的重定向,如果这样的话,我们url加密的目的就没有实现了,url重定向,会将解密的url传递到客户端,这就让我们的url暴露了,这完全和我们的设想相反,果断放弃。

第二块石头:使用IHttpHandler

  之后查资料时,有提到使用IhttpHandler的ProcessRequest处理web请求的。

  1. filterContext.RequestContext.HttpContext.RewritePath(url);//url为虚拟路径
  2. IHttpHandler httpHandler = new MvcHttpHandler();
  3. httpHandler.ProcessRequest(System.Web.HttpContext.Current);

这样也可以达到目的,但是如果你的action参数有非string类型的,那么在执行这个方法时会报错,虽然你看不到,但是你在Global.asax.cs的Application_Error方法中使用Server.GetLastError().GetBaseException();捕获异常,你会发现类似xxxxxx方法需要的int类型的参数,但是传递过来的是string类型等等。功能虽然实现了,但是看着就是不爽,所以继续摸索下一个方案。

第三块石头:使用ActionParameters修改context的参数

  写代码就是要要耐心,经过我漫长的摸索,我发现没有加密的url时,ActionExecutingContext的ActionParameters属性就是url的查询参数集合,是一个Dictionary<string,object>的类型;但是如果对url进行加密,ActionParameters的参数集合里面只有key,没有value,所以我就想,能不能通过修改ActionParameters里面的值,然后在带调用其父类ActionFilterAttribute的OnActionExecuting方法,话不多说,贴出实现的代码。

  1. //获取访问Action参数的描述,主要是参数的类型和参数名称
  2.              ParameterDescriptor[] pds = filterContext.ActionDescriptor.GetParameters();
  3. 2
  4. 3 //重新填充参数
  5. 4 string paramName = "";
  6. 5 string paramValue = "";
  7. 6 foreach (string param in parameters)
  8. 7 {
  9. 8 paramName = param.Split('=')[0];
  10. 9 paramValue = HttpUtility.UrlDecode(param.Split('=')[1]);
  11. 10 foreach (ParameterDescriptor pd in pds)
  12. 11 {
  13. 12 if (paramName == pd.ParameterName)
  14. 13 {
  15. 14 //判断参数的类型,如果是整形的数据,那么将参数转换成整形数据
  16. 15 if (pd.ParameterType.Name.ToLower() == "int32" || pd.ParameterType.Name.ToLower() == "nullable`1")
  17. 16 {
  18. 17 filterContext.ActionParameters.Add(paramName, Convert.ToInt32(paramValue));
  19. 18 }
  20. 19 else
  21. 20 {
  22. 21 filterContext.ActionParameters.Add(paramName, paramValue);
  23. 22 }
  24. 23 break;
  25. 24 }
  26. 25 }
  27. 26
  28. 27 }
  29. 28 }
  30. 29 base.OnActionExecuting(filterContext);

  不过下面和大家分享一下,使用参数替换过程中遇到的问题和值得注意的几点。

  1、在添加参数之前,一定要先使用Clear()方法清楚默认生成的参数,不然重新添加参数时,会出现“字典中已经存在此key的值”;还有一种的方法就是遍历传递过来的参数和ActionParameters的中的参数,替换参数的值。

  2、第二点要注意的是参数的类型,参数的类型和名称可以通过ActionDestriptor方法获取,如果传递的参数类型与Action定义的参数类型不一致,会引发参数类型不一致的异常。

  3、最后要注意的可空类型的参数,如果action的参数饱含可空类型的非空类型的参数,当可空参数有值时,那么其余的所有参数都要传递,并且赋值。最简单的办法就是遍历ActionDestriptor的参数,将所有的参数都加到ActionParameters中并附上值。

  1. //如果饱含可空参数,那么需要不可空的并且不在请求参数列表中的参数添加到参数列表,否则会报错
  2. 30 foreach (ParameterDescriptor pd in pds)
  3. 31 {
  4. 32 if (!filterContext.ActionParameters.Keys.Contains(pd.ParameterName))
  5. 33 {
  6. 34 if (pd.ParameterType.Name.ToLower() == "nullable`1")
  7. 35 {
  8. 36 filterContext.ActionParameters.Add(pd.ParameterName, null);
  9. 37 }
  10. 38 else if (pd.DefaultValue == null)
  11. 39 {
  12. 40 filterContext.ActionParameters.Add(pd.ParameterName, "");
  13. 41 }
  14. 42 else
  15. 43 {
  16. 44 filterContext.ActionParameters.Add(pd.ParameterName, pd.DefaultValue);
  17. 45 }
  18. 46 }
  19. 47 }

利用MVC的过滤器实现url的参数加密和解密的更多相关文章

  1. [转]java利用AES实现URL的参数加密

    原文地址:http://h5566h.iteye.com/blog/1465426 很多时候需要在URL传参,希望URL参数能够加密,这里我结合了文章http://www.2cto.com/kf/20 ...

  2. ASP.NET - URL中参数加密解密操作

    效果: 代码: using System; using System.Text; using System.IO; using System.Security.Cryptography; public ...

  3. JS URL 使用base64加密与解密

    JS编码方式: <script type="text/javascript"> document.write(encodeURI("http://www.w3 ...

  4. JS URL 使用base64加密与解密和MD5解密

    JS编码方式: <script type="text/javascript"> document.write(encodeURI("http://www.w3 ...

  5. 基于RequestBodyAdvice和ResponseBodyAdvice来实现spring中参数的加密和解密

    在日常开发中,有时候我们经常需要和第三方接口打交道,有时候是我们调用别人的第三方接口,有时候是别人在调用我们的第三方接口,那么为了调用接口的安全性,一般都会对传输的数据进行加密操作,如果每个接口都由我 ...

  6. ASP.NET MVC中获取URL地址参数的两种写法

    一.url地址传参的第一种写法 1.通过mvc中默认的url地址书写格式:控制器/方法名/参数 2.实例:http://localhost:39270/RequestDemo/Index/88,默认参 ...

  7. mvc url路由参数的加密和解密

    查看某个信息的时候一般会在url上加上该信息在数据库中对应的主键id(而且一般是自增的) url是这样子的 xxxDetail/1 , 虽然对于我们开发人员来说可以这种显式的数据库主键会方便调试过程, ...

  8. Spring MVC url提交参数和获取参数

    [转载:http://blog.csdn.net/mahoking] 普通URL提交参数         该格式url为:url.do?param1=mahc&param2=8888.00 需 ...

  9. Spring Mvc Url和参数名称忽略大小写

    在开发过程中Spring Mvc 默认 Url和参数名称都是区分大小写的 比如:www.a.com/user/getUserInfo?userId=1 www.a.com/user/getuserIn ...

随机推荐

  1. shell脚本学习之Bash shell 里各种括号的用法

    今天在 SegmentFault 上看到又有人问起关于Shell里各种括号的问题.对于很多玩Shell的人,括号是个很尴尬的问题,用起来没问题,说起来不明白,我在这里总结一下Bash Shell几种括 ...

  2. ios 用LLDB查看模拟器文件路径以及一些常用的命令

    我看网络上有好多有关lldb调试命令的介绍,我都看了一遍,都没有这个方法,所以我在这里补充出来,帮助需要的人. 另外附上一些 实用LLDB命令 我们可以使用e命令定义变量 (lldb) e NSStr ...

  3. why slow thinking wins

    今天Hacker News上的一篇文章<为什么想得慢的人能赢>引起了广泛的讨论. 网友Scott Burson在文章后评论说:"之前,我雇佣了一位TopCoder冠军,原本预计他 ...

  4. 一个js加css加html完成的HTML

    效果图: 代码: HTML: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "htt ...

  5. LuaNode 开源库

    受CJSON库的启发,用C++实现解析Lua文件的库. 整个库大概800行代码,因为新鲜出炉,所以有些潜在问题尚未发现. 截图中包含使用例子. 以下接口清单: LuaNode(); LuaNode(c ...

  6. hdu 1018 Big Number (数学题)

    Problem Description Inmany applications very large integers numbers are required. Some of theseappli ...

  7. ES 中文分词

    一.大名鼎鼎的中文插件IK的安装配置 1. 在插件目录中建立IK的目录 mkdir $ES_HOME/plugins/analysis-ik 2. 下载IK 的类库jar 文件到IK目录 cd $ES ...

  8. 引入的iframe是跨域的, 如何控制其高度

    前提是你有编辑这个跨域的iframe的权限!! 1. main-domain.html (main display HTML) <!DOCTYPE html> <html> & ...

  9. ES6-个人学习笔记二--解构赋值

    第二期,解构赋值如果能够熟练应用确实是个十分方便的功能,但是过分的依赖和嵌套只会让代码理解和维护起来十分困难,是个体现高逼格的表达式呢~ 1,解构赋值的基础 //定义:es6运行按照一定模式,从数组或 ...

  10. ubuntu14.04下 Android虚拟机 genymotion 的下载和安装

    官网:https://www.genymotion.com/ Install Guide https://www.genymotion.com/#!/developers/user-guide#ins ...