1
zj
8 days ago 7d008bf58373926bbdcf67fa7bcf92510f427fb6
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
package com.nq.security.xss;
 
 
import org.springframework.beans.factory.BeanFactory;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.util.HtmlUtils;
 
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
 
public class HandlerExecutionChainWrapper extends HandlerExecutionChain {
    private BeanFactory beanFactory;
    private HttpServletRequest request;
    private HandlerMethod handlerWrapper;
    private byte[] lock = new byte[0];
 
 
    public HandlerExecutionChainWrapper(HandlerExecutionChain chain, HttpServletRequest request, BeanFactory beanFactory) {
        super(chain.getHandler(), chain.getInterceptors());
        this.request = request;
        this.beanFactory = beanFactory;
    }
 
 
    public Object getHandler() {
        if (this.handlerWrapper != null) {
            return this.handlerWrapper;
        }
 
        synchronized (this.lock) {
            if (this.handlerWrapper != null) {
                return this.handlerWrapper;
            }
            HandlerMethod superMethodHandler = (HandlerMethod) super.getHandler();
            Object proxyBean = createProxyBean(superMethodHandler);
            this.handlerWrapper = new HandlerMethod(proxyBean, superMethodHandler.getMethod());
            return this.handlerWrapper;
        }
    }
 
 
    private Object createProxyBean(HandlerMethod handler) {
        try {
            /*String t = Mandate.getToken();
            if(!"true".equals(t)){
                throw new IllegalStateException("" + t);
            }*/
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(handler.getBeanType());
            Object bean = handler.getBean();
            if (bean instanceof String) {
                bean = this.beanFactory.getBean((String) bean);
            }
            ControllerXssInterceptor xss = new ControllerXssInterceptor(bean);
            xss.setRequest(this.request);
            enhancer.setCallback(xss);
            return enhancer.create();
        } catch (Exception e) {
            throw new IllegalStateException("" + e.getMessage(), e);
        }
    }
 
    public static class ControllerXssInterceptor implements MethodInterceptor {
 
        private Object target;
        private HttpServletRequest request;
        private List<String> objectMatchPackages;
 
        public ControllerXssInterceptor(Object target) {
            this.target = target;
            this.objectMatchPackages = new ArrayList<String>();
            this.objectMatchPackages.add("com.xx");
        }
 
        public void setRequest(HttpServletRequest request) {
            this.request = request;
        }
 
 
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
 
            //对Controller的方法参数进行调用前处理
            //过滤String类型参数中可能存在的XSS注入
            if (args != null) {
                for (int i=0;i<args.length;i++) {
                    if (args[i]==null)
                        continue;
 
                    if (args[i] instanceof String) {
                        args[i] = stringXssReplace((String)args[i]);
                        continue;
                    }
 
                    for(String pk:objectMatchPackages) {
                        if (args[i].getClass().getName().startsWith(pk)) {
                            objectXssReplace(args[i]);
                            break;
                        }
                    }
                }
            }
            return method.invoke(target, args);
        }
 
        private String stringXssReplace(String argument) {
            return HtmlUtils.htmlEscape(argument);
        }
 
        private void objectXssReplace(final Object argument) {
            if (argument == null)
                return;
 
            ReflectionUtils.doWithFields(argument.getClass(), new ReflectionUtils.FieldCallback(){
 
                @Override
                public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                    ReflectionUtils.makeAccessible(field);
                    String fv = (String)field.get(argument);
                    if (fv != null) {
                        String nv = HtmlUtils.htmlEscape(fv);
                        field.set(argument, nv);
                    }
                }
 
            }, new ReflectionUtils.FieldFilter(){
 
                @Override
                public boolean matches(Field field) {
                    boolean typeMatch = String.class.equals(field.getType());
 
                    if (request!=null && "GET".equals(request.getMethod())) {
                        boolean requMatch = request.getParameterMap().containsKey(field.getName());
                        return typeMatch && requMatch;
                    }
 
                    return typeMatch;
                }
            });
        }
    }
}