当前位置:   article > 正文

springMvc+nginx文件鉴权(校验权限)服务器_springmvc文件鉴权

springmvc文件鉴权

目录

一、环境

二、需求

三、原来访问文件的方式

四、使用nginx+springmvc做文件鉴权服务器

五、代码实现

        1、访问系统路径时跳转到nginx

        2、配置nginx

        3、系统鉴权方法

六、其他问题


一、环境

        springmvc开发的javaweb系统。

二、需求

        需要鉴权后才能访问上传的文件(指定文件夹中的文件)。

三、原来访问文件的方式

        1、使用tomcat做文件服务器,通过tomcat的server.xml配置文件的访问路径。

        

        2、特点:不需要鉴权就能访问文件

        3、访问路径:http:localhost:8080/download/test.png

        注意:http:localhost:8080为系统访问路径,我这里的文件服务器和系统服务器用的同一个tomcat

四、使用nginx+springmvc做文件鉴权服务器

        1、为了不改变系统原有的功能,访问路径不变:http:localhost:8080/download/test.png

        2、问题:在访问路径不变的情况下需要访问nginx,鉴权的功能需要交给系统后台校验,校验完成后发送给nginx做文件的访问。

        3、对应问题可以知道文件的整个访问过程猜想:

                ①:访问系统路径时跳转到nginx

                ②:nginx跳转到系统进行鉴权

                ③:系统鉴权完成后跳转到nginx

                ④:nginx访问文件

五、代码实现

        1、访问系统路径时跳转到nginx

                ①:通过spring的过滤器,过滤包含/download/的路径。在web.xml添加过滤器

  1. <filter>
  2. <filter-name>downloadFileFilter</filter-name>
  3. <filter-class>cn.o.DownloadFileFilter</filter-class>
  4. </filter>
  5. <filter-mapping>
  6. <filter-name>downloadFileFilter</filter-name>
  7. <url-pattern>/download/*</url-pattern>
  8. </filter-mapping>

                ②:DownloadFileFilter代码

  1. package cn.o;
  2. import cn.o.account.LoginAccount;
  3. import cn.o.utils.StringUtils;
  4. import javax.servlet.*;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. import java.net.URI;
  9. import java.net.URISyntaxException;
  10. public class DownloadFileFilter implements Filter {
  11. @Override
  12. public void init(FilterConfig filterConfig) throws ServletException {
  13. }
  14. @Override
  15. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  16. HttpServletRequest request = (HttpServletRequest) servletRequest;
  17. HttpServletResponse response = (HttpServletResponse) servletResponse;
  18. //获取ip,应对使用ip或者域名进行访问
  19. URI uri = URI.create(request.getRequestURL().toString());
  20. String ip = null ;
  21. try {
  22. ip = (new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), null, null, null)).getHost();
  23. } catch (URISyntaxException e) {
  24. e.printStackTrace();
  25. }
  26. if(StringUtils.isNotBlank(ip)){
  27. //文件nginx服务器端口
  28. String fileNginxPort = "8081";
  29. //我这里项目登录会把账号信息存储到session中
  30. //这里先简单校验是否有账号信息,后面会具体校验账号有效性
  31. LoginAccount loginAccount = (LoginAccount) request.getSession().getAttribute("login_account");
  32. if(loginAccount != null){
  33. String url = request.getRequestURL().toString();
  34. if(url.indexOf("/download/") >= 0){
  35. String redirectUrl = "http://"+ip+":"+fileNginxPort+"/"+url.substring(url.indexOf("/download"),url.length());
  36. //重定向跳转到nginx服务器
  37. response.sendRedirect(redirectUrl);
  38. }
  39. }
  40. }
  41. filterChain.doFilter(request, response);
  42. }
  43. @Override
  44. public void destroy() {
  45. }
  46. }

        2、配置nginx

                ①:配置nginx.conf,注意:每个server的server_name和proxy_pass的ip要一致。

                ②:rewrite 配置的就是需要跳转的鉴权方法地址。

                ③:alias 配置的是鉴权成功后文件的物理地址。

                到这一步,我们上面猜想的②、③、④就由nginx帮我们实现交互了,接下来就是鉴权代码的实现了。

  1. #user nobody;
  2. worker_processes 1;
  3. #error_log logs/error.log;
  4. #error_log logs/error.log notice;
  5. #error_log logs/error.log info;
  6. #pid logs/nginx.pid;
  7. events {
  8. worker_connections 1024;
  9. }
  10. http {
  11. include mime.types;
  12. default_type application/octet-stream;
  13. sendfile on;
  14. keepalive_timeout 65;
  15. # 这个是内网ip的server, 如果有多个ip映射访问,就配置多个server
  16. server {
  17. # nginx服务器端口
  18. listen 8081;
  19. server_name 192.168.1.1;
  20. location / {
  21. root html;
  22. index index.html index.htm;
  23. }
  24. # 文件服务
  25. location ^~ /download {
  26. # 内部请求(即一次请求的Nginx内部请求),禁止外部访问,重要。
  27. internal;
  28. # 文件的物理路径
  29. alias E:/demo/xinfengxian/download/;
  30. limit_rate 200k;
  31. # 浏览器访问返回200,然后转由后台处理
  32. error_page 404 =200 @backend;
  33. }
  34. # 文件鉴权
  35. location @backend {
  36. # 去掉访问路径中的 /download/,然后定义需要跳转的系统鉴权方法。
  37. rewrite ^/download/(.*)$ /authentication/loadFile/$1 break;
  38. # 这里是系统服务器地址
  39. proxy_pass http://192.168.1.1:8080;
  40. proxy_redirect off;
  41. proxy_set_header Host $host;
  42. proxy_set_header X-Real-IP $remote_addr;
  43. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  44. }
  45. error_page 500 502 503 504 /50x.html;
  46. location = /50x.html {
  47. root html;
  48. }
  49. }
  50. # 这个是本地ip的server
  51. server {
  52. listen 8081;
  53. server_name 127.0.0.1;
  54. location / {
  55. root html;
  56. index index.html index.htm;
  57. }
  58. # 文件下载服务
  59. location ^~ /download {
  60. # 内部请求(即一次请求的Nginx内部请求),禁止外部访问,重要。
  61. internal;
  62. # 文件的物理路径
  63. alias E:/demo/xinfengxian/download/;
  64. limit_rate 200k;
  65. # 浏览器访问返回200,然后转由后台处理
  66. error_page 404 =200 @backend;
  67. }
  68. # 文件下载鉴权
  69. location @backend {
  70. # 去掉访问路径中的 /download/,然后定义需要跳转的系统鉴权方法。
  71. rewrite ^/download/(.*)$ /attachPermissions/downAttach/$1 break;
  72. # 这里是系统服务器地址
  73. proxy_pass http://127.0.0.1:8080;
  74. proxy_redirect off;
  75. proxy_set_header Host $host;
  76. proxy_set_header X-Real-IP $remote_addr;
  77. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  78. }
  79. error_page 500 502 503 504 /50x.html;
  80. location = /50x.html {
  81. root html;
  82. }
  83. }
  84. # 这个是域名的server
  85. server {
  86. listen 8081;
  87. server_name mytest.test.com;
  88. location / {
  89. root html;
  90. index index.html index.htm;
  91. }
  92. # 文件下载服务
  93. location ^~ /download {
  94. # 内部请求(即一次请求的Nginx内部请求),禁止外部访问,重要。
  95. internal;
  96. # 文件的物理路径
  97. alias E:/demo/xinfengxian/download/;
  98. limit_rate 200k;
  99. # 浏览器访问返回200,然后转由后台处理
  100. error_page 404 =200 @backend;
  101. }
  102. # 文件下载鉴权
  103. location @backend {
  104. # 去掉访问路径中的 /download/,然后定义需要跳转的系统鉴权方法。
  105. rewrite ^/download/(.*)$ /attachPermissions/downAttach/$1 break;
  106. # 这里是系统服务器地址
  107. proxy_pass http://mytest.test.com:8080;
  108. proxy_redirect off;
  109. proxy_set_header Host $host;
  110. proxy_set_header X-Real-IP $remote_addr;
  111. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  112. }
  113. error_page 500 502 503 504 /50x.html;
  114. location = /50x.html {
  115. root html;
  116. }
  117. }
  118. }

        3、系统鉴权方法

  1. package cn.o.authentication;
  2. import org.apache.commons.lang.StringUtils;
  3. import org.springframework.context.annotation.Scope;
  4. import org.springframework.stereotype.Controller;
  5. import org.springframework.web.bind.annotation.PathVariable;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RequestMethod;
  8. import javax.servlet.http.HttpServletRequest;
  9. import javax.servlet.http.HttpServletResponse;
  10. @Controller
  11. @RequestMapping("/authentication")
  12. @Scope("prototype")
  13. public class AttachPermissionsController {
  14. @RequestMapping(value = "/loadFile/**/{fileName:.+}",method = RequestMethod.GET)
  15. public void loadFile(HttpServletRequest request, HttpServletResponse response,@PathVariable String fileName) throws Exception{
  16. LoginAccount loginAccount = (LoginAccount) request.getSession().getAttribute("login_account");
  17. String loginToken = "";// 登录的token
  18. String loginName = "";// 登录的用户名
  19. boolean flag = false;
  20. if(loginAccount != null){
  21. loginName = loginAccount.getName();
  22. //根据用户名获取token,我这里是将登录的token存放到session缓存中,适用于简单的校验,最好还是使用redis等缓存机制
  23. loginToken = (String) request.getSession().getAttribute(loginName+"_login_token");
  24. if(StringUtils.isNotBlank(loginToken)){
  25. //我这里使用的是JWTUtil工具类生成token的,所以我这里是用JWTUtil工具类校验token的有效性的
  26. //这里就不贴具体校验方法了,
  27. String pass = "通过";
  28. if ("通过".equals(pass)) {// 如果通过,说明此token还有效,否则视为无效
  29. flag = true;
  30. } else {
  31. flag = false;
  32. }
  33. }else{
  34. flag = false;
  35. }
  36. }else{
  37. flag = false;
  38. }
  39. //如果上面的鉴权通过,则允许文件访问
  40. if(flag){
  41. String requestUri = request.getRequestURI();
  42. requestUri = requestUri.substring(requestUri.indexOf("/")+1);
  43. requestUri = requestUri.substring(requestUri.indexOf("/")+1);
  44. requestUri = requestUri.substring(requestUri.indexOf("/")+1);
  45. // 已被授权访问
  46. // 文件下载
  47. response.setHeader("Content-Disposition", "attachment; filename=\"" + new String(fileName.getBytes("GBK"), "iso-8859-1") + "\"");
  48. // 文件以二进制流传输
  49. response.setHeader("Content-Type", "application/octet-stream;charset=utf-8");
  50. // 返回真实文件路径交由 Nginx 处理,保证前端无法看到真实的文件路径。
  51. // 这里的 "/download" 为 Nginx 中配置的下载服务名
  52. response.setHeader("X-Accel-Redirect", "/download/"+requestUri);
  53. // 限速,单位字节,默认不限
  54. // response.setHeader("X-Accel-Limit-Rate","1024");
  55. // 是否使用Nginx缓存,默认yes
  56. // response.setHeader("X-Accel-Buffering","yes");
  57. response.setHeader("X-Accel-Charset", "utf-8");
  58. // 禁止浏览器缓存
  59. response.setHeader("Pragma", "No-cache");
  60. response.setHeader("Cache-Control", "No-cache");
  61. response.setHeader("Expires", "0");
  62. }else{
  63. response.setStatus(404);
  64. return;
  65. }
  66. }
  67. }

      还有个大家要注意的,如果同时使用tomcat和nginx配置文件服务器,会只进入到tomcat中,所以如果要使用nginx鉴权,要将tomcat的文件配置删除。

六、其他问题

        在开发的过程中,web.xml原本配置了不同类型的静态资源,导致了使用nginx服务器后访问不了配置了静态资源的文件。

        在网上找了解决方法:将需要通过nginx服务器访问的类型的静态资源配置删掉,并且在spring配置文件中添加<mvc:default-servlet-handler/>,具体在哪里添加和原因自行百度一下

  1. <!--静态资源-->
  2. <servlet-mapping>
  3. <servlet-name>default</servlet-name>
  4. <url-pattern>*.png</url-pattern>
  5. </servlet-mapping>

到这里就全部完成了,代码是原有的项目修改后贴出来的,表达能力不太好,有些地方写得不好,大家将就着看吧。配置或者代码有比较好优化可以交流交流

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/182371
推荐阅读
相关标签
  

闽ICP备14008679号