zjs před 1 měsícem
rodič
revize
0c959b9845

+ 5 - 0
ruoyi-admin/pom.xml

@@ -119,6 +119,11 @@
119 119
             <version>3.3.3</version>
120 120
         </dependency>
121 121
         -->
122
+        <dependency>
123
+            <groupId>org.apache.pdfbox</groupId>
124
+            <artifactId>pdfbox</artifactId>
125
+            <version>2.0.31</version>
126
+        </dependency>
122 127
     </dependencies>
123 128
 
124 129
     <build>

+ 2 - 2
ruoyi-admin/src/main/java/com/ruoyi/web/controller/cas/CASLoginController.java

@@ -200,8 +200,8 @@ public class CASLoginController {
200 200
      * @param loginBody 登录信息
201 201
      * @return 结果
202 202
      */
203
-    @RequestMapping("/postcheck/login")
204
-    @ResponseBody
203
+//    @RequestMapping("/postcheck/login")
204
+//    @ResponseBody
205 205
     public AjaxResult casLogin(@RequestBody LoginBody loginBody, HttpServletRequest request) {
206 206
 //        String serverLoginUrl = casConfig.getServerLoginUrl();
207 207
 //        String serverLogoutUrl = casConfig.getServerLogoutUrl();

+ 13 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java

@@ -14,6 +14,7 @@ import javax.servlet.http.HttpServletResponse;
14 14
 import com.ruoyi.common.annotation.Anonymous;
15 15
 import com.ruoyi.common.utils.AntiVirus;
16 16
 import com.ruoyi.postCheck.service.IPostCheckedService;
17
+import com.ruoyi.web.controller.utils.PdfUtils;
17 18
 import io.swagger.annotations.Api;
18 19
 import io.swagger.annotations.ApiImplicitParam;
19 20
 import io.swagger.annotations.ApiImplicitParams;
@@ -103,6 +104,18 @@ public class CommonController {
103 104
             if (!AntiVirus.scanFileName(file.getOriginalFilename())) {
104 105
                 return AjaxResult.error("危险文件,不可以上传。");
105 106
             }
107
+            // 文件后缀
108
+            String fileNameXSS = file.getOriginalFilename();
109
+            String suffix = fileNameXSS.substring(fileNameXSS.lastIndexOf(".") + 1).toLowerCase();
110
+
111
+            // 判断是否是pdf文件类型
112
+            if (StringUtils.equals(suffix, "pdf")) {
113
+                // 判断文件xss攻击
114
+                boolean haveJavaScript = PdfUtils.containsJavaScript(PdfUtils.multipartFileToFile(file));
115
+                if (haveJavaScript) {
116
+//                    return ("对不起,您上传的文件[" + fileName + "]包含xss脚本代码!");
117
+                }
118
+            }
106 119
 //            System.out.println("file ============================= " + file);
107 120
 //            System.out.println("unid ============================= " + unid);
108 121
 //            System.out.println("returnImage ============================= " + returnImage);

+ 95 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/utils/PdfUtils.java

@@ -0,0 +1,95 @@
1
+package com.ruoyi.web.controller.utils;
2
+
3
+
4
+import com.ruoyi.common.utils.uuid.UUID;
5
+import lombok.extern.log4j.Log4j2;
6
+import org.apache.pdfbox.pdmodel.PDDocument;
7
+import org.springframework.web.multipart.MultipartFile;
8
+
9
+import java.io.*;
10
+
11
+/**
12
+ * @Author: Ljx
13
+ * @Date: 2023/12/20
14
+ **/
15
+@Log4j2
16
+public class PdfUtils {
17
+
18
+    /**
19
+     * 获取不带扩展名的文件名
20
+     */
21
+    public static String getFileNameNoSuffix(String filename) {
22
+        if ((filename != null) && (filename.length() > 0)) {
23
+            int dot = filename.lastIndexOf('.');
24
+            if ((dot > -1) && (dot < (filename.length()))) {
25
+                return filename.substring(0, dot);
26
+            }
27
+        }
28
+        return filename;
29
+    }
30
+
31
+    /**
32
+     * 获取文件扩展名
33
+     */
34
+    public static String getSuffixNameName(String filename) {
35
+        if ((filename != null) && (filename.length() > 0)) {
36
+            int dot = filename.lastIndexOf('.');
37
+            if ((dot > -1) && (dot < (filename.length() - 1))) {
38
+                return filename.substring(dot + 1);
39
+            }
40
+        }
41
+        return filename;
42
+    }
43
+
44
+
45
+    /**
46
+     * File转MultipartFile
47
+     *
48
+     * @param mulFile 文件对象
49
+     * @return Multipart文件对象
50
+     */
51
+    public static File multipartFileToFile(MultipartFile mulFile) throws IOException {
52
+        InputStream ins = mulFile.getInputStream();
53
+        String fileName = mulFile.getOriginalFilename();
54
+        String prefix = getFileNameNoSuffix(fileName) + UUID.randomUUID().toString();
55
+        String suffix = "." + getSuffixNameName(fileName);
56
+        File toFile = File.createTempFile(prefix, suffix);
57
+        OutputStream os = new FileOutputStream(toFile);
58
+        int bytesRead = 0;
59
+        byte[] buffer = new byte[8192];
60
+        while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
61
+            os.write(buffer, 0, bytesRead);
62
+        }
63
+        os.close();
64
+        ins.close();
65
+        return toFile;
66
+    }
67
+
68
+
69
+    /**
70
+     * 校验pdf文件是否包含js脚本
71
+     **/
72
+    public static boolean containsJavaScript(File file) throws IOException {
73
+
74
+//        RandomAccessFile is = new RandomAccessFile(file, "r");
75
+        try (PDDocument document = PDDocument.load(file)){
76
+            String CosName = document.getDocument().getTrailer().toString();
77
+            if (CosName.contains("COSName{JavaScript}")
78
+                    || CosName.contains("COSName{JS}")
79
+                    || CosName.contains("COSName{alert}")
80
+                    || CosName.contains("COSName{onmouseover}")
81
+                    || CosName.contains("COSName{alalertert}")
82
+                    || CosName.contains("COSName{embed}")
83
+            ) {
84
+                return true;
85
+            }
86
+        } catch (Exception e) {
87
+            log.error("PDF效验异常:" + e.getMessage());
88
+            return true;
89
+        }
90
+        return false;
91
+    }
92
+
93
+
94
+
95
+}

+ 20 - 0
ruoyi-common/src/main/java/com/ruoyi/common/filter/MyResponseHeaderFilter.java

@@ -0,0 +1,20 @@
1
+package com.ruoyi.common.filter;
2
+
3
+import org.springframework.stereotype.Component;
4
+
5
+import javax.servlet.*;
6
+import javax.servlet.http.HttpServletResponse;
7
+import java.io.IOException;
8
+
9
+@Component
10
+public class MyResponseHeaderFilter implements Filter {
11
+    //防止站点劫持
12
+    @Override
13
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
14
+            throws IOException, ServletException {
15
+        HttpServletResponse res = (HttpServletResponse) response;
16
+        res.setHeader("X-Frame-Options", "SAMEORIGIN");
17
+        chain.doFilter(request, response);
18
+    }
19
+
20
+}

+ 44 - 0
ruoyi-common/src/main/java/com/ruoyi/common/filter/RestCorsFilter.java

@@ -0,0 +1,44 @@
1
+package com.ruoyi.common.filter;
2
+
3
+import org.springframework.core.Ordered;
4
+import org.springframework.core.annotation.Order;
5
+import org.springframework.stereotype.Component;
6
+
7
+import javax.servlet.*;
8
+import javax.servlet.http.HttpServletRequest;
9
+import javax.servlet.http.HttpServletResponse;
10
+import java.io.IOException;
11
+
12
+@Component
13
+@Order(Ordered.HIGHEST_PRECEDENCE)
14
+public class RestCorsFilter implements Filter {
15
+
16
+    public RestCorsFilter() {
17
+    }
18
+
19
+    @Override
20
+    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
21
+        HttpServletResponse response = (HttpServletResponse) res;
22
+        HttpServletRequest request = (HttpServletRequest) req;
23
+        response.setHeader("Access-Control-Allow-Origin", "*"); // 可写成受信任的站点
24
+        response.setHeader("Access-Control-Allow-Credentials","true");
25
+        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
26
+        response.setHeader("Access-Control-Max-Age", "31536000");
27
+        response.setHeader("Access-Control-Allow-Headers", "*");
28
+        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
29
+            response.setStatus(HttpServletResponse.SC_OK);
30
+        } else {
31
+            chain.doFilter(req, res);
32
+        }
33
+    }
34
+
35
+    @Override
36
+    public void init(FilterConfig filterConfig) {
37
+    }
38
+
39
+
40
+
41
+    @Override
42
+    public void destroy() {
43
+    }
44
+}

+ 10 - 1
ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java

@@ -3,6 +3,8 @@ package com.ruoyi.framework.config;
3 3
 import java.util.HashMap;
4 4
 import java.util.Map;
5 5
 import javax.servlet.DispatcherType;
6
+
7
+import com.ruoyi.common.filter.MyResponseHeaderFilter;
6 8
 import org.springframework.beans.factory.annotation.Value;
7 9
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
8 10
 import org.springframework.boot.web.servlet.FilterRegistrationBean;
@@ -54,5 +56,12 @@ public class FilterConfig
54 56
         registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
55 57
         return registration;
56 58
     }
57
-
59
+    @Bean
60
+    public FilterRegistrationBean<MyResponseHeaderFilter> clickJackingProtectionFilter() {
61
+        FilterRegistrationBean<MyResponseHeaderFilter> registrationBean = new FilterRegistrationBean<>();
62
+        registrationBean.setFilter(new MyResponseHeaderFilter());
63
+        registrationBean.addUrlPatterns("/*");
64
+        registrationBean.setOrder(1);
65
+        return registrationBean;
66
+    }
58 67
 }