情况是这样的,现在公司的网站有一个更新产品的功能,就是用户输入激活码,然后我们会判断数据库中的记录以及他的下载权限,有的话则给处对应的下载链接,用户点链接(现在给出的是实际地址)就可以去下载一个更新文件,然后是对更新是有控制的,分为1次性下载,一段时间内可任意下载,以及永久任意下载。但是现在问题在于拥有1次性和一段时间下载权限的用户,他们可以记录下载地址,那么以后不用输入激活码不用经过判断就可以直接下载更新,就会破坏更新的规则,今天突然想到这个,所以对下载做了如下处理:
生成下载链接的时候,随机生成一个字符串,设置到session中(叫做token)同时往页面上传递同一个值(用tok表示),并将真实下载地址加密,下载的链接改成download.jsp?加密地址&tok
EncryptUtil eu = new EncryptUtil();//使用默认密钥加密 String enurl = eu.encrypt(forDown.getLink());//加密URL String token = StringUtil.getInstance().getString(7);//生成令牌 request.getSession().setAttribute("tok",token);//设置令牌 sb.append("right|"+forDown.getName()+"|"+enurl+"|"+token); //这里是用ajax返回到页面上,页面上截取字符串生成链接 response.getWriter().print(sb.toString());
生成URL
var info = data.split('|'); $('#showlink').empty().append('<span>'+info[1]+'</span><a href="download.jsp?url='+info[2]+'&t='+info[3]+'">点击这里下载更新包</a>');
在download.jsp上判断session中的token和request来的tok是否相同,相同则将加密地址解密还原,并随机生成另一个字符串,设置到session中,覆盖token,然后服务器跳转,跳往真实下载地址。这样的话用户复制地址不论粘贴到哪,只要下载过后就都会因为token和tok对不上号而下载不了了。
String url = request.getParameter("url"); EncryptUtil eu = new EncryptUtil();//加密解密类 String rUrl = eu.decrypt(url);//解密成下载的真实url String tok = request.getParameter("t");//获取页面上的令牌 String token = (String)session.getAttribute("tok");//获取session中的令牌 String newToken = StringUtil.getInstance().getString(7);//生成令牌 if(tok.equals(token)){ session.setAttribute("tok",newToken);//设置令牌 request.getRequestDispatcher(rUrl).forward(request,response); }else{ response.sendRedirect("index.jsp"); }
但是我不太确定这样做是不是很安全,首先习惯用工具下载文件的用户来说这个链接是没法用工具下了,而且对于一次下载的用户来说,如果半路取消则再也不能下载了(因为生成链接后下载次数就清空了),所以目前的问题总结如下:
1、我对限制下载的处理是否安全?
2、可不可以提供一些其他的建议或者思路在这样防止重复下载的场合?
3、对于一次性下载的用户,是否可以用输出流提供下载,判断输出流完成后再清空次数?(有别的思路也请多多指教啦)