yxh
3 天以前 1603d54adf0063eb01549e2bfa9ba5860ca3d863
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package com.ruoyi.framework.interceptor;
 
 
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.StringUtils;
import jdk.nashorn.internal.objects.annotations.Where;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.stereotype.Component;
 
import java.sql.Connection;
import java.util.Properties;
 
import static com.ruoyi.common.utils.SecurityUtils.getLoginUser;
 
@Component
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class HospitalFilterInterceptor implements Interceptor {
 
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 获取 StatementHandler
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
 
        // 解包代理对象,获取真正的目标对象
        MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
        while (metaObject.hasGetter("h")) {
            Object target = metaObject.getValue("h");
            metaObject = SystemMetaObject.forObject(target);
        }
        while (metaObject.hasGetter("target")) {
            Object target = metaObject.getValue("target");
            metaObject = SystemMetaObject.forObject(target);
        }
 
        // 获取原始 SQL
        String originalSql = (String) metaObject.getValue("delegate.boundSql.sql");
 
        // 获取当前 guid
        String guid = null;
        try {
            LoginUser loginUser = getLoginUser();
            if (!ObjectUtils.isEmpty(loginUser)) {
                guid = loginUser.getUser().getGuid();
            }
        } catch (Exception e) {
 
        }
        if (StringUtils.isEmpty(guid)) {
            return invocation.proceed();
        }
 
        // 修改 SQL,添加 guid 条件
        String modifiedSql = modifySqlWithGuidId(originalSql, guid);
 
        // 将修改后的 SQL 写回
        metaObject.setValue("delegate.boundSql.sql", modifiedSql);
        System.out.println("修改后的 SQL:" + modifiedSql);
 
        // 执行后续操作
        return invocation.proceed();
    }
 
    /**
     * 修改 SQL,注入 guid 条件
     *
     * @param originalSql 原始 SQL
     * @param guid        当前医院 ID
     * @return 修改后的 SQL
     */
    private String modifySqlWithGuidId(String originalSql, String guid) {
        if (originalSql.contains("insert into") || originalSql.contains("INSERT INTO")) return originalSql;
        // 提取 GUID 的 WHERE 子句
        String whereClause = " guid = '" + guid + "'";
 
        // 正则表达式查找 FROM 或 JOIN 的表定义
        String fromPattern = "(?i)(FROM|JOIN)\\s+(\\w+)(?:\\s+(\\w+))?";
        java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(fromPattern);
        java.util.regex.Matcher matcher = pattern.matcher(originalSql);
 
        String tableOrAlias = ""; // 保存主表名或别名
        if (matcher.find()) {
            // 优先匹配第一个表名或别名
            tableOrAlias = matcher.group(3) != null ? matcher.group(3) : matcher.group(2);
        }
 
        // 如果找到表名或别名,为 WHERE 子句添加前缀
        if (!tableOrAlias.isEmpty()) {
            whereClause = tableOrAlias.toUpperCase() + "." + whereClause;
            if (whereClause.contains("WHERE. guid")) {
                whereClause = whereClause.replaceAll("WHERE. guid", "guid");
            }
        }
 
        // 修改 SQL
        if (originalSql.toUpperCase().contains("WHERE")) {
            // 在已有 WHERE 后添加 GUID 条件
            return originalSql.replaceFirst("(?i)WHERE", "WHERE " + whereClause + " AND ");
        } else {
            // 如果没有 WHERE,检查是否有 ORDER BY 或 LIMIT
            int orderByIndex = originalSql.toUpperCase().indexOf("ORDER BY");
            int limitIndex = originalSql.toUpperCase().indexOf("LIMIT");
            int groupByIndex = originalSql.toUpperCase().indexOf("GROUP BY");
 
            // 如果存在 ORDER BY 或 LIMIT,插入 GUID 条件
            if (orderByIndex > 0 || limitIndex > 0 || groupByIndex > 0) {
                // 确保在 ORDER BY 或 LIMIT 前添加 WHERE 子句
                // 确定插入 GUID 条件的位置
                int insertPos = originalSql.length();  // 默认在 SQL 末尾
 
                // 找到最早出现的子句位置(ORDER BY, GROUP BY, LIMIT)
                if (orderByIndex > 0) insertPos = Math.min(insertPos, orderByIndex);
                if (groupByIndex > 0) insertPos = Math.min(insertPos, groupByIndex);
                if (limitIndex > 0) insertPos = Math.min(insertPos, limitIndex);
                String s = originalSql.substring(0, insertPos) + " WHERE " + whereClause + " " + originalSql.substring(insertPos);
                if (s.contains("LIMIT. guid")) {
                    s = s.replace("LIMIT. guid", "guid");
                }
                if (s.contains("ORDER BY. guid")) {
                    s = s.replace("ORDER BY. guid", "guid");
                }
                if (s.contains("ORDER. guid")) {
                    s = s.replace("ORDER. guid", "guid");
                }
                if (s.contains("GROUP BY. guid")) {
                    s = s.replace("GROUP BY. guid", "guid");
                }
                if (s.contains("GROUP. guid")) {
                    s = s.replace("GROUP. guid", "guid");
                }
                return s;
            } else {
                // 如果没有 WHERE,也没有 ORDER BY 或 LIMIT,直接加 WHERE
                return originalSql + " WHERE " + whereClause;
            }
        }
    }
 
    @Override
    public Object plugin(Object target) {
        // 包装目标对象
        return Plugin.wrap(target, this);
    }
 
    @Override
    public void setProperties(Properties properties) {
        // 可设置插件的参数(暂时无需设置)
    }
}