个人博客原文地址:url动态加解密 | DevotedWife's Yard.
表单提交(或其他需要请求后台url)的场景下,url对于客户端来说是可见的,攻击者可以通过url猜测到很多信息并伪造请求对url进行攻击。本文探讨了一种对 url加密和解密的方案,并给出了关键代码。
Form表单提交
-
页面form的action地址加密:
先在原始url之前添加
encoded/
(或其他)以方便后台认证是否合法url;
在加密后的url地址后加.do
(或其他)以方便filter过滤。1 2 3 4 5 6 7 8 9 10
<% String url = DesUtil.encrypt("encoded/test/second.htm"); %> <form action="<%=url%>.do" method="post"> <input type="text" id="account" name="j_username" class="text " placeholder="请输入手机号/邮箱" value="tangliu"/> <input type="text" id="password" name="j_password" class="text " placeholder="请输入密码" value="123456"/> <input type="submit" value="Submit" /> </form>
-
自定义一个filter,放在其他filter之前:
1 2 3 4 5 6 7 8 9
<filter> <filter-name>decodeFilter</filter-name> <filter-class>com.tangliu.test.encodeurl.DecodeUrlFilter</filter-class> <async-supported>true</async-supported> </filter> <filter-mapping> <filter-name>decodeFilter</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping>
-
filter中对url进行解密,若解密后的url不符合规范(不是以”encoded/“开头),则抛弃,否则对url请求进行forward转发。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { try { HttpServletRequest httpRequest = (HttpServletRequest) request; String encodedUrl = httpRequest.getRequestURI(); encodedUrl = encodedUrl.substring(1, (encodedUrl.length() - 3)); String unencodedUrl = DesUtil.decrypt(encodedUrl); //如果解密后不是以encoded开头则说明不是合法请求,抛弃 if(!unencodedUrl.startsWith("encoded")) return; unencodedUrl = unencodedUrl.replace("encoded/", ""); unencodedUrl = httpRequest.getContextPath() + unencodedUrl; request.getRequestDispatcher("/" + unencodedUrl).forward(request, response); } catch (Exception e) { e.printStackTrace(); } }
-
经过测试,froward转发的url可以被其他filter正确拦截,于此同时地址栏显示的是加密后的url,设置如下:
| |
其中`<dispatcher>`标签如果不设置,默认是REQUEST,表示拦截客户端请求,`FORWARD`表示拦截内部的forward请求。
-
同时最后收到请求的controller,能够正常接收request的参数:
1 2 3 4 5 6 7 8 9
@RequestMapping(value = "second", method = RequestMethod.POST) @ResponseBody public String service(HttpServletRequest request) { System.out.println(request.getParameter("j_username")); System.out.println(request.getParameter("j_password")); return "test"; }
使用ajax post提交
-
在
<meta>
中写入加密后的url地址:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
<meta name="formUrl" content="<%=DesUtil.encrypt("encoded/test/second.htm")%>.do"> <script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script> <script> function ajaxTest(){ var url = $("meta[name='formUrl']").attr("content"); var data = {}; data['j_username'] = 'tangliu'; data['j_password'] = '123456'; $.post(url, data, function(result){ alert(result); }); } </script>
-
在
<script>
中写入加密后的url地址:1 2 3 4 5 6 7 8 9 10 11 12
<script> function ajaxTest(){ var url = "<%=DesUtil.encrypt("encoded/test/second.htm")%>.do"; var data = {}; data['j_username'] = 'tangliu'; data['j_password'] = '123456'; $.post(url, data, function(result){ alert(result); }); } </script>
测试可行。