有时候我们在项目里面有需要提供给外界下载东西的链接(如先让用户下载我们给定的模板,然后让用户填完之后再上传)这时我们不得不对外开放我们的资源路径,如果用最简单的方式将项目内的资源路径暴露在页面供用户下载就涉及到了安全隐患,不法分子可能会根据我们提供的路径猜测到其他路径进行非法操作等等。

下面,介绍自己亲测可行的解决方案:

先贴上整个Demo的目录结构:

借用一个对url进行加密解密的工具类UrlUtil:

package com.zy.web.common;import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.SecureRandom;public class UrlUtil {private static final String KEY = "myYouMw6qPt&3AD";//这个KEY值可以任意指定,相当于一个密钥private static final Logger LOGGER = LoggerFactory.getLogger(UrlUtil.class);public static String enCryptAndEncode(String content) {try {byte[] sourceBytes = enCryptAndEncode(content, KEY);return Base64.encodeBase64URLSafeString(sourceBytes);} catch (Exception e) {LOGGER.error(e.getMessage(), e);return content;}}/*** 加密函数** @param content 加密的内容* @param strKey  密钥* @return 返回二进制字符数组* @throws Exception*/public static byte[] enCryptAndEncode(String content, String strKey) throws Exception {KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");keyGenerator.init(128, new SecureRandom(strKey.getBytes()));SecretKey desKey = keyGenerator.generateKey();Cipher cipher = Cipher.getInstance("AES");cipher.init(Cipher.ENCRYPT_MODE, desKey);return cipher.doFinal(content.getBytes("UTF-8"));}public static String deCryptAndDecode(String content) throws Exception {byte[] targetBytes = Base64.decodeBase64(content);return deCryptAndDecode(targetBytes, KEY);}/*** 解密函数** @param src    加密过的二进制字符数组* @param strKey 密钥* @return* @throws Exception*/public static String deCryptAndDecode(byte[] src, String strKey) throws Exception {KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");keyGenerator.init(128, new SecureRandom(strKey.getBytes()));SecretKey desKey = keyGenerator.generateKey();Cipher cipher = Cipher.getInstance("AES");cipher.init(Cipher.DECRYPT_MODE, desKey);byte[] cByte = cipher.doFinal(src);return new String(cByte, "UTF-8");}
}

web.xml中配置springmvc的两种常用的拦截方式

 <!-- springMVC前端控制器 --><servlet><servlet-name>DownloadDemo</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- contextConfigLocation不是必须的, 如果不配置contextConfigLocation, springmvc的配置文件默认在:WEB-INF/servlet的name+"-servlet.xml" --><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/springmvc.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>DownloadDemo</servlet-name><!-- 拦截所有请求jsp除外 --><url-pattern>/</url-pattern></servlet-mapping><servlet-mapping><servlet-name>DownloadDemo</servlet-name><url-pattern>*.action</url-pattern></servlet-mapping>

在跳转到有下载链接的页面之前,在controller中进行如下处理:

package com.zy.web.controller;import javax.servlet.http.HttpServletRequest;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import com.zy.web.common.UrlUtil;@Controller
@RequestMapping("/page")
public class PageController {@RequestMapping("/toDownloadPage")public String toDownloadPage(HttpServletRequest request){String path = "/files/我的文件.docx";//这里指定页面上供用户下载的文件路径 我这里是从webapp目录下开始String pathEn = UrlUtil.enCryptAndEncode(path);request.setAttribute("path", pathEn);return "download/downloadPage";}}

在有下载链接的页面中,该有链接的地方做如下处理:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>下载页面</title>
</head>
<body><a href="${pageContext.request.contextPath}/download/${path}">下载资源1</a><br/><a href="${pageContext.request.contextPath}/download1/test.action?url=${path}">下载资源2</a>
</body>
</html>

启动项目后访问该页面效果如下:(亲测兼容IE7及以上)  这样就很难猜测项目的其他路径

然后当用户点击下载链接,后台controller应该这样处理:

Restfull风格的url对应的后台处理:

package com.zy.web.controller;import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;import com.zy.web.common.UrlUtil;@Controller
public class DownloadController{private static final Logger logger = LoggerFactory.getLogger(DownloadController.class);@RequestMapping("/download/{param}")public void downloadFile(HttpServletRequest request,HttpServletResponse response,@PathVariable("param") String param){InputStream fis = null;BufferedInputStream bis = null;BufferedOutputStream bos = null;try {String decodeUrl = UrlUtil.deCryptAndDecode(param);String fileName = decodeUrl.substring(decodeUrl.lastIndexOf("/") + 1);response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); response.setContentType("application/x-msdownload");String filePath = request.getSession().getServletContext().getRealPath("") + decodeUrl;File file = new File(filePath);fis = new FileInputStream(file);bis = new BufferedInputStream(fis);bos = new BufferedOutputStream(response.getOutputStream());int len = 0;byte[] bs = new byte[1024];while((len = bis.read(bs)) != -1){bos.write(bs, 0, len);}bos.flush();bos.close();} catch (Exception e) {logger.error("download file exception:",e);} finally {if (fis != null) {try {fis.close();} catch (IOException e) {logger.error("IO close exception:",e);}}if (bos != null) {try {bos.close();} catch (IOException e) {logger.error("IO close exception:",e);}}}}
}

常用的*.action或*.do的url对应的后台处理:

package com.zy.web.controller;import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import com.zy.web.common.UrlUtil;@Controller
public class DownloadController1{private static final Logger logger = LoggerFactory.getLogger(DownloadController1.class);@RequestMapping("/download1/test")public void downloadFile(HttpServletRequest request,HttpServletResponse response){InputStream fis = null;BufferedInputStream bis = null;BufferedOutputStream bos = null;try {String decodeUrl = UrlUtil.deCryptAndDecode(request.getParameter("url"));String fileName = decodeUrl.substring(decodeUrl.lastIndexOf("/") + 1);response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); response.setContentType("application/x-msdownload");String filePath = request.getSession().getServletContext().getRealPath("") + decodeUrl;File file = new File(filePath);fis = new FileInputStream(file);bis = new BufferedInputStream(fis);bos = new BufferedOutputStream(response.getOutputStream());int len = 0;byte[] bs = new byte[1024];while((len = bis.read(bs)) != -1){bos.write(bs, 0, len);}bos.flush();bos.close();} catch (Exception e) {logger.error("download file exception:",e);} finally {if (fis != null) {try {fis.close();} catch (IOException e) {logger.error("IO close exception:",e);}}if (bos != null) {try {bos.close();} catch (IOException e) {logger.error("IO close exception:",e);}}}}
}

这样就能让浏览器正确地下载到项目里面希望用户能够下载的资源而避免安全隐患了。(同时解决下载文件名为中文乱码问题)

企业提供下载链接的安全解决方案相关推荐

  1. 2020年国内最新最优目标检测(完结篇)提供下载链接

    点击蓝字关注我们 computerVision 计算机视觉战队 ● 扫码关注,回复:目标检测 ● 获取目标检测相关下载链接 今天我们的目标检测综述最后一章,也是这个系列的完结,希望有兴趣的同学可以从中 ...

  2. iOS开发UI篇—推荐两个好用的Xcode插件(提供下载链接)

    iOS开发UI篇-推荐两个好用的Xcode插件(提供下载链接) 这里推荐两款好用的Xcode插件,并提供下载链接. 一.插件和使用如下: 1.两款插件 对项目中图片提供自动提示功能的插件:KSImag ...

  3. iOS酷我音乐导出工具使用说明和原理介绍(提供下载链接及project源代码)

    软件下载链接 酷我音乐ios版下载的音乐文件.通过同步助手等软件查看时.发现音乐文件都是一串数字命名.通过网上查找和自己尝试.发现那些文件都是音频文件改了文件名称而已.仅仅要改动回文件名称,就能和正常 ...

  4. iOS酷我音乐导出工具使用说明和原理介绍(提供下载链接及工程源码)

    软件下载链接 酷我音乐ios版下载的音乐文件,通过同步助手等软件查看时,发现音乐文件都是一串数字命名.通过网上查找和自己尝试,发现那些文件都是音频文件改了文件名而已.只要修改回文件名,就能和正常的音乐 ...

  5. 转载 |「智链ChainNova」要为企业提供一站式服务及行业解决方案

    本文来自36氪战略合作区块链媒体"Odaily星球日报",可点击[阅读原文]查看. 尽管区块链技术还处于早期阶段,但在企业级区块链平台这一赛道,早已挤满了诸如 IBM.亚马逊.腾讯 ...

  6. 收集的网络上大型的开源图像处理软件代码(提供下载链接)

    要写好一个图像处理软件,仅靠自己看书是完全不够的,要多方面学习,借鉴前人的经验,要集思广益.多面出击.如今网络发达,图像学的资料其实也到处都是.只是往往个人能力或精力有限,在短时间内无法找到那些也许藏 ...

  7. Neo4j在Windows下的安装,提供下载链接(官网忒慢)

    第一步:下载Neo4j压缩包 官网下载地址:https://neo4j.com/download-center/ 百度网盘下载地址:链接:https://pan.baidu.com/s/1hygHS6 ...

  8. 图像处理开源软件代码网站汇总(提供下载链接)

    在学习过程中查阅到的一些资源并进行整理,在此分享给有需要的同学,同时也方便后续查阅学习. 如有侵权,请联系删除,如有错误,欢迎大家指正,谢谢 在慢慢的摸索和累积中也找到了一些相关资料,共享给大家学习. ...

  9. 电子发票+SaaS服务,票加加为企业提供票税智能管理解决方案

    2012年年初,国家税务总局在<网络发票管理办法(征求意见稿)>中表示,国家将积极推广使用网络发票管理系统开具发票. 2013年6月27日,北京市正是开展电子发票应用试点. 2017年3月 ...

  10. 第十四届全国大学生智能车竞赛竞赛技术报告下载链接

    第十四届智能车竞赛技术报告下载链接 01 下载报告   今天上午,看到有同学询问关于十四届智能车竞赛技术报告下载的询问. 实际上,之前第十四届的技术报告在百度上有, 只是没有能够提供下载链接. 由于第 ...

最新文章

  1. AFNetWorking 队列请求
  2. heroes 2 android,英雄出击2游戏下载-英雄出击2Heroes Strike2中文安卓版下载v0.0.5- 游侠下载站...
  3. v-for中为什么要有key属性
  4. 深入解读:KubeVela 与 PaaS 有何不同?
  5. 无限超越超级机器人nds_阿里重新定义个人电脑!仅名片大小,无限升级,不怕丢失无惧病毒,价格仅传统PC一半...
  6. BugkuCTF-MISC题做个游戏
  7. 总结一下切换git地址 重合代码的过程
  8. 力扣104. 二叉树的最大深度(JavaScript)
  9. 导入 SQL 时出现 Invalid default value for ‘create_time‘ 报错解决方法
  10. 学校与工作(献于在校大学生及入职不久的工作者)
  11. 易语言超级列表框怎么设置文本颜色_抖音超火的快闪动画怎么做?手把手教你!三分钟学会...
  12. R语言 多元方差分析|单因素方差分析
  13. psd导出jpg太大_PSD源文件、导出JPG\PNG格式文件过大解决办法
  14. 以后不该吃的不能吃了。。。
  15. 世界首富马斯克突然吟了一首中文诗
  16. matlab自带的VAD检测程序
  17. html5弹性盒做成骰子,弹性盒制作骰子
  18. 【计科二班】编程测试题解
  19. 小学信息技术 计算机组装,浅谈小学信息技术教学创新
  20. 如何保证电脑硬盘格式化后数据不能被恢复?

热门文章

  1. [CSS]CSS 字体属性
  2. 手机奥维地图在测量中的应用
  3. 代码整洁之道——如何写出整洁高效的代码
  4. Beyond Compare 提示“缺少评估信息或损坏”
  5. 解决Linux下adb devices找不到设备
  6. ubuntu upgrade problem
  7. 【CodeChef-LYRC】Music Lyrics【AC自动机】
  8. windows家庭版关闭windows defender
  9. Win7 启用Guest账户,设置登录界面不显示 Guest账户
  10. 2022-2027年中国缝制机械行业市场全景评估及发展战略规划报告