赞
踩
目录
springmvc开发的javaweb系统。
需要鉴权后才能访问上传的文件(指定文件夹中的文件)。
1、使用tomcat做文件服务器,通过tomcat的server.xml配置文件的访问路径。
2、特点:不需要鉴权就能访问文件
3、访问路径:http:localhost:8080/download/test.png
注意:http:localhost:8080为系统访问路径,我这里的文件服务器和系统服务器用的同一个tomcat
1、为了不改变系统原有的功能,访问路径不变:http:localhost:8080/download/test.png
2、问题:在访问路径不变的情况下需要访问nginx,鉴权的功能需要交给系统后台校验,校验完成后发送给nginx做文件的访问。
3、对应问题可以知道文件的整个访问过程猜想:
①:访问系统路径时跳转到nginx
②:nginx跳转到系统进行鉴权
③:系统鉴权完成后跳转到nginx
④:nginx访问文件
①:通过spring的过滤器,过滤包含/download/的路径。在web.xml添加过滤器
- <filter>
- <filter-name>downloadFileFilter</filter-name>
- <filter-class>cn.o.DownloadFileFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>downloadFileFilter</filter-name>
- <url-pattern>/download/*</url-pattern>
- </filter-mapping>
②:DownloadFileFilter代码
- package cn.o;
-
- import cn.o.account.LoginAccount;
- import cn.o.utils.StringUtils;
-
- import javax.servlet.*;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
- import java.net.URI;
- import java.net.URISyntaxException;
-
- public class DownloadFileFilter implements Filter {
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
-
- }
-
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
- HttpServletRequest request = (HttpServletRequest) servletRequest;
- HttpServletResponse response = (HttpServletResponse) servletResponse;
- //获取ip,应对使用ip或者域名进行访问
- URI uri = URI.create(request.getRequestURL().toString());
- String ip = null ;
- try {
- ip = (new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), null, null, null)).getHost();
- } catch (URISyntaxException e) {
- e.printStackTrace();
- }
- if(StringUtils.isNotBlank(ip)){
- //文件nginx服务器端口
- String fileNginxPort = "8081";
- //我这里项目登录会把账号信息存储到session中
- //这里先简单校验是否有账号信息,后面会具体校验账号有效性
- LoginAccount loginAccount = (LoginAccount) request.getSession().getAttribute("login_account");
- if(loginAccount != null){
- String url = request.getRequestURL().toString();
- if(url.indexOf("/download/") >= 0){
- String redirectUrl = "http://"+ip+":"+fileNginxPort+"/"+url.substring(url.indexOf("/download"),url.length());
- //重定向跳转到nginx服务器
- response.sendRedirect(redirectUrl);
- }
- }
- }
- filterChain.doFilter(request, response);
- }
-
- @Override
- public void destroy() {
-
- }
- }
①:配置nginx.conf,注意:每个server的server_name和proxy_pass的ip要一致。
②:rewrite 配置的就是需要跳转的鉴权方法地址。
③:alias 配置的是鉴权成功后文件的物理地址。
到这一步,我们上面猜想的②、③、④就由nginx帮我们实现交互了,接下来就是鉴权代码的实现了。
-
- #user nobody;
- worker_processes 1;
-
- #error_log logs/error.log;
- #error_log logs/error.log notice;
- #error_log logs/error.log info;
-
- #pid logs/nginx.pid;
-
-
- events {
- worker_connections 1024;
- }
-
-
- http {
- include mime.types;
- default_type application/octet-stream;
-
- sendfile on;
-
- keepalive_timeout 65;
-
- # 这个是内网ip的server, 如果有多个ip映射访问,就配置多个server
- server {
- # nginx服务器端口
- listen 8081;
- server_name 192.168.1.1;
-
- location / {
- root html;
- index index.html index.htm;
- }
- # 文件服务
- location ^~ /download {
- # 内部请求(即一次请求的Nginx内部请求),禁止外部访问,重要。
- internal;
- # 文件的物理路径
- alias E:/demo/xinfengxian/download/;
- limit_rate 200k;
- # 浏览器访问返回200,然后转由后台处理
- error_page 404 =200 @backend;
- }
-
- # 文件鉴权
- location @backend {
- # 去掉访问路径中的 /download/,然后定义需要跳转的系统鉴权方法。
- rewrite ^/download/(.*)$ /authentication/loadFile/$1 break;
- # 这里是系统服务器地址
- proxy_pass http://192.168.1.1:8080;
- proxy_redirect off;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- }
-
- error_page 500 502 503 504 /50x.html;
- location = /50x.html {
- root html;
- }
- }
-
- # 这个是本地ip的server
- server {
- listen 8081;
- server_name 127.0.0.1;
-
- location / {
- root html;
- index index.html index.htm;
- }
- # 文件下载服务
- location ^~ /download {
- # 内部请求(即一次请求的Nginx内部请求),禁止外部访问,重要。
- internal;
- # 文件的物理路径
- alias E:/demo/xinfengxian/download/;
- limit_rate 200k;
- # 浏览器访问返回200,然后转由后台处理
- error_page 404 =200 @backend;
- }
-
- # 文件下载鉴权
- location @backend {
- # 去掉访问路径中的 /download/,然后定义需要跳转的系统鉴权方法。
- rewrite ^/download/(.*)$ /attachPermissions/downAttach/$1 break;
- # 这里是系统服务器地址
- proxy_pass http://127.0.0.1:8080;
- proxy_redirect off;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- }
-
- error_page 500 502 503 504 /50x.html;
- location = /50x.html {
- root html;
- }
- }
-
- # 这个是域名的server
- server {
- listen 8081;
- server_name mytest.test.com;
-
- location / {
- root html;
- index index.html index.htm;
- }
- # 文件下载服务
- location ^~ /download {
- # 内部请求(即一次请求的Nginx内部请求),禁止外部访问,重要。
- internal;
- # 文件的物理路径
- alias E:/demo/xinfengxian/download/;
- limit_rate 200k;
- # 浏览器访问返回200,然后转由后台处理
- error_page 404 =200 @backend;
- }
-
- # 文件下载鉴权
- location @backend {
- # 去掉访问路径中的 /download/,然后定义需要跳转的系统鉴权方法。
- rewrite ^/download/(.*)$ /attachPermissions/downAttach/$1 break;
- # 这里是系统服务器地址
- proxy_pass http://mytest.test.com:8080;
- proxy_redirect off;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- }
-
- error_page 500 502 503 504 /50x.html;
- location = /50x.html {
- root html;
- }
- }
- }
- package cn.o.authentication;
-
- import org.apache.commons.lang.StringUtils;
- import org.springframework.context.annotation.Scope;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.PathVariable;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- @Controller
- @RequestMapping("/authentication")
- @Scope("prototype")
- public class AttachPermissionsController {
-
- @RequestMapping(value = "/loadFile/**/{fileName:.+}",method = RequestMethod.GET)
- public void loadFile(HttpServletRequest request, HttpServletResponse response,@PathVariable String fileName) throws Exception{
- LoginAccount loginAccount = (LoginAccount) request.getSession().getAttribute("login_account");
- String loginToken = "";// 登录的token
- String loginName = "";// 登录的用户名
- boolean flag = false;
- if(loginAccount != null){
- loginName = loginAccount.getName();
- //根据用户名获取token,我这里是将登录的token存放到session缓存中,适用于简单的校验,最好还是使用redis等缓存机制
- loginToken = (String) request.getSession().getAttribute(loginName+"_login_token");
- if(StringUtils.isNotBlank(loginToken)){
- //我这里使用的是JWTUtil工具类生成token的,所以我这里是用JWTUtil工具类校验token的有效性的
- //这里就不贴具体校验方法了,
- String pass = "通过";
- if ("通过".equals(pass)) {// 如果通过,说明此token还有效,否则视为无效
- flag = true;
- } else {
- flag = false;
- }
- }else{
- flag = false;
- }
- }else{
- flag = false;
- }
-
- //如果上面的鉴权通过,则允许文件访问
- if(flag){
- String requestUri = request.getRequestURI();
- requestUri = requestUri.substring(requestUri.indexOf("/")+1);
- requestUri = requestUri.substring(requestUri.indexOf("/")+1);
- requestUri = requestUri.substring(requestUri.indexOf("/")+1);
- // 已被授权访问
- // 文件下载
- response.setHeader("Content-Disposition", "attachment; filename=\"" + new String(fileName.getBytes("GBK"), "iso-8859-1") + "\"");
- // 文件以二进制流传输
- response.setHeader("Content-Type", "application/octet-stream;charset=utf-8");
- // 返回真实文件路径交由 Nginx 处理,保证前端无法看到真实的文件路径。
- // 这里的 "/download" 为 Nginx 中配置的下载服务名
- response.setHeader("X-Accel-Redirect", "/download/"+requestUri);
- // 限速,单位字节,默认不限
- // response.setHeader("X-Accel-Limit-Rate","1024");
- // 是否使用Nginx缓存,默认yes
- // response.setHeader("X-Accel-Buffering","yes");
- response.setHeader("X-Accel-Charset", "utf-8");
-
- // 禁止浏览器缓存
- response.setHeader("Pragma", "No-cache");
- response.setHeader("Cache-Control", "No-cache");
- response.setHeader("Expires", "0");
- }else{
- response.setStatus(404);
- return;
- }
- }
- }
还有个大家要注意的,如果同时使用tomcat和nginx配置文件服务器,会只进入到tomcat中,所以如果要使用nginx鉴权,要将tomcat的文件配置删除。
在开发的过程中,web.xml原本配置了不同类型的静态资源,导致了使用nginx服务器后访问不了配置了静态资源的文件。
在网上找了解决方法:将需要通过nginx服务器访问的类型的静态资源配置删掉,并且在spring配置文件中添加<mvc:default-servlet-handler/>,具体在哪里添加和原因自行百度一下
- <!--静态资源-->
- <servlet-mapping>
- <servlet-name>default</servlet-name>
- <url-pattern>*.png</url-pattern>
- </servlet-mapping>
到这里就全部完成了,代码是原有的项目修改后贴出来的,表达能力不太好,有些地方写得不好,大家将就着看吧。配置或者代码有比较好优化可以交流交流
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。