diff --git a/doc/XXL-JOB官方文档.md b/doc/XXL-JOB官方文档.md
index 1a825994..796671a7 100644
--- a/doc/XXL-JOB官方文档.md
+++ b/doc/XXL-JOB官方文档.md
@@ -923,7 +923,7 @@ spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
-### 调度中心通讯TOKEN [选填]:非空时启用;
+### 调度中心通讯TOKEN [必填]:安全性校验;
xxl.job.accessToken=
### 调度中心通讯超时时间[选填],单位秒;默认3s;
@@ -1016,7 +1016,7 @@ xuxueli/xxl-job-admin:{指定版本}
```
### 调度中心部署根地址 [必填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
xxl.job.admin.addresses=http://127.0.0.1:8080
-### 调度中心通讯TOKEN [选填]:非空时启用;
+### 调度中心通讯TOKEN [必填]:安全性校验;
xxl.job.admin.accessToken=default_token
### 调度中心通讯超时时间[选填],单位秒;默认3s;
xxl.job.admin.timeout=3
@@ -2904,6 +2904,7 @@ alter table xxl_job_log
### 7.47 版本 v3.5.0 Release Notes[ING]
- 1、【新增】GLUE模式开关:新增GLUE模式开关(xxl.job.executor.glueenabled),支持执行器维度设置是否启用GLUE模式;
- 2、【TODO】执行器AccessToken:执行器维度AccessToken,线上化动态管理;执行器间AccessToken隔离,提升安全性;
+ - 执行器 AccessToken:
- 3、【TODO】调度中心OpenAPI增强:提供任务管理能力;封装Agent Skill并推送ClawHub;
- 4、【TODO】配置线上化:发送邮箱配置线上管理、线程池配置调整;
- 5、【TODO】任务告警:拆分“告警类型、告警配置”属性,支持Webhook、邮箱多种方式;
diff --git a/pom.xml b/pom.xml
index 73be234d..bec6e587 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,7 +33,7 @@
2.0.18
- 6.1.0
+ 6.0.3
3.0.0
diff --git a/xxl-job-admin/src/test/java/com/xxl/job/openapi/ExecutorBizTest.java b/xxl-job-admin/src/test/java/com/xxl/job/openapi/ExecutorBizTest.java
index d2d03520..bf3926e5 100644
--- a/xxl-job-admin/src/test/java/com/xxl/job/openapi/ExecutorBizTest.java
+++ b/xxl-job-admin/src/test/java/com/xxl/job/openapi/ExecutorBizTest.java
@@ -22,12 +22,14 @@ public class ExecutorBizTest {
private static String addressUrl = "http://127.0.0.1:9999/";
private static String accessToken = "default_token";
+ private static String appname = "xxl-job-executor-sample";
private ExecutorBiz buildClient(){
return HttpTool.createClient()
.url(addressUrl)
.timeout(3 * 1000)
.header(Const.XXL_JOB_ACCESS_TOKEN, accessToken)
+ .header(Const.XXL_JOB_APPNAME, appname)
.proxy(ExecutorBiz.class);
}
@@ -36,12 +38,12 @@ public class ExecutorBizTest {
ExecutorBiz executorBiz = buildClient();
// Act
final Response retval = executorBiz.beat();
+ logger.info("retval:{}", retval);
// Assert result
Assertions.assertNotNull(retval);
Assertions.assertNull(((Response) retval).getData());
Assertions.assertEquals(200, retval.getCode());
- Assertions.assertNull(retval.getMsg());
}
@Test
diff --git a/xxl-job-core/src/main/java/com/xxl/job/core/constant/Const.java b/xxl-job-core/src/main/java/com/xxl/job/core/constant/Const.java
index 45cf27cc..3e4c6fe6 100644
--- a/xxl-job-core/src/main/java/com/xxl/job/core/constant/Const.java
+++ b/xxl-job-core/src/main/java/com/xxl/job/core/constant/Const.java
@@ -12,6 +12,11 @@ public class Const {
*/
public static final String XXL_JOB_ACCESS_TOKEN = "XXL-JOB-ACCESS-TOKEN";
+ /**
+ * app name
+ */
+ public static final String XXL_JOB_APPNAME = "XXL-JOB-APPNAME";
+
// ---------------------- for registry ----------------------
diff --git a/xxl-job-core/src/main/java/com/xxl/job/core/executor/XxlJobExecutor.java b/xxl-job-core/src/main/java/com/xxl/job/core/executor/XxlJobExecutor.java
index bbe9f52f..9477c159 100644
--- a/xxl-job-core/src/main/java/com/xxl/job/core/executor/XxlJobExecutor.java
+++ b/xxl-job-core/src/main/java/com/xxl/job/core/executor/XxlJobExecutor.java
@@ -140,6 +140,9 @@ public class XxlJobExecutor {
if (StringTool.isBlank(appname)) {
throw new RuntimeException("xxl-job executor appname empty.");
}
+ if (StringTool.isBlank(accessToken)) {
+ throw new RuntimeException("xxl-job executor accessToken empty.");
+ }
// bind instance
xxlJobExecutor = this;
diff --git a/xxl-job-core/src/main/java/com/xxl/job/core/server/EmbedServer.java b/xxl-job-core/src/main/java/com/xxl/job/core/server/EmbedServer.java
index 09db7199..6dcf47ec 100644
--- a/xxl-job-core/src/main/java/com/xxl/job/core/server/EmbedServer.java
+++ b/xxl-job-core/src/main/java/com/xxl/job/core/server/EmbedServer.java
@@ -3,11 +3,12 @@ package com.xxl.job.core.server;
import com.xxl.job.core.constant.Const;
import com.xxl.job.core.executor.XxlJobExecutor;
import com.xxl.job.core.openapi.executor.ExecutorBiz;
-import com.xxl.job.core.openapi.executor.impl.ExecutorBizImpl;
import com.xxl.job.core.openapi.executor.dto.IdleBeatRequest;
import com.xxl.job.core.openapi.executor.dto.KillRequest;
import com.xxl.job.core.openapi.executor.dto.LogRequest;
import com.xxl.job.core.openapi.executor.dto.TriggerRequest;
+import com.xxl.job.core.openapi.executor.impl.ExecutorBizImpl;
+import com.xxl.tool.core.StringTool;
import com.xxl.tool.error.ThrowableTool;
import com.xxl.tool.json.GsonTool;
import com.xxl.tool.response.Response;
@@ -83,7 +84,7 @@ public class EmbedServer {
.addLast(new IdleStateHandler(0, 0, 30 * 3, TimeUnit.SECONDS)) // beat 3N, close if idle
.addLast(new HttpServerCodec())
.addLast(new HttpObjectAggregator(5 * 1024 * 1024)) // merge request & reponse to FULL
- .addLast(new EmbedHttpServerHandler(executorBiz, xxlJobExecutor.getAccessToken(), bizThreadPool));
+ .addLast(new EmbedHttpServerHandler(executorBiz, xxlJobExecutor, bizThreadPool));
}
})
.childOption(ChannelOption.SO_KEEPALIVE, true);
@@ -143,32 +144,33 @@ public class EmbedServer {
public static class EmbedHttpServerHandler extends SimpleChannelInboundHandler {
private static final Logger logger = LoggerFactory.getLogger(EmbedHttpServerHandler.class);
- private ExecutorBiz executorBiz;
- private String accessToken;
- private ThreadPoolExecutor bizThreadPool;
+ private final ExecutorBiz executorBiz;
+ private final XxlJobExecutor xxlJobExecutor;
+ private final ThreadPoolExecutor bizThreadPool;
- public EmbedHttpServerHandler(ExecutorBiz executorBiz, String accessToken, ThreadPoolExecutor bizThreadPool) {
+ public EmbedHttpServerHandler(final ExecutorBiz executorBiz, final XxlJobExecutor xxlJobExecutor, final ThreadPoolExecutor bizThreadPool) {
this.executorBiz = executorBiz;
- this.accessToken = accessToken;
+ this.xxlJobExecutor = xxlJobExecutor;
this.bizThreadPool = bizThreadPool;
}
@Override
protected void channelRead0(final ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {
+
// request parse
- //final byte[] requestBytes = ByteBufUtil.getBytes(msg.content()); // byteBuf.toString(io.netty.util.CharsetUtil.UTF_8);
- String requestData = msg.content().toString(CharsetUtil.UTF_8);
- String uri = msg.uri();
HttpMethod httpMethod = msg.method();
+ String uri = msg.uri();
+ String requestData = msg.content().toString(CharsetUtil.UTF_8);
boolean keepAlive = HttpUtil.isKeepAlive(msg);
- String accessTokenReq = msg.headers().get(Const.XXL_JOB_ACCESS_TOKEN);
+ String accessToken = msg.headers().get(Const.XXL_JOB_ACCESS_TOKEN);
+ String appname = msg.headers().get(Const.XXL_JOB_APPNAME);
// invoke
bizThreadPool.execute(new Runnable() {
@Override
public void run() {
// do invoke
- Object responseObj = dispatchRequest(httpMethod, uri, requestData, accessTokenReq);
+ Object responseObj = dispatchRequest(httpMethod, uri, requestData, accessToken, appname);
// to json
String responseJson = GsonTool.toJson(responseObj);
@@ -179,7 +181,10 @@ public class EmbedServer {
});
}
- private Object dispatchRequest(HttpMethod httpMethod, String uri, String requestData, String accessTokenReq) {
+ /**
+ * dispatch request
+ */
+ private Object dispatchRequest(HttpMethod httpMethod, String uri, String requestData, String accessToken, String appname) {
// valid
if (HttpMethod.POST != httpMethod) {
return Response.ofFail("invalid request, HttpMethod not support.");
@@ -187,10 +192,14 @@ public class EmbedServer {
if (uri == null || uri.trim().isEmpty()) {
return Response.ofFail( "invalid request, uri-mapping empty.");
}
- if (accessToken != null
- && !accessToken.trim().isEmpty()
- && !accessToken.equals(accessTokenReq)) {
- return Response.ofFail("The access token is wrong.");
+
+ // valid access token
+ if (StringTool.isBlank(accessToken) || StringTool.isBlank(appname)) {
+ return Response.ofFail("invalid request, accessToken or appname is empty.");
+ }
+ if (!(accessToken.equals(xxlJobExecutor.getAccessToken())
+ && appname.equals(xxlJobExecutor.getAppname()))) {
+ return Response.ofFail("invalid request, accessToken or appname invalid.");
}
// services mapping