diff --git a/src/main/java/net/geedge/asw/common/util/Constants.java b/src/main/java/net/geedge/asw/common/util/Constants.java index 620856a..2300658 100644 --- a/src/main/java/net/geedge/asw/common/util/Constants.java +++ b/src/main/java/net/geedge/asw/common/util/Constants.java @@ -6,6 +6,7 @@ import java.io.File; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public class Constants { @@ -104,6 +105,11 @@ public class Constants { public static final Map ENV_TERMINAL_WEBSOCKET_SESSION = T.MapUtil.newHashMap(); + public static final ConcurrentHashMap RUNNING_JOB_THREAD = new ConcurrentHashMap<>(); + + public static final ConcurrentHashMap RESULT_JOB_THREAD = new ConcurrentHashMap<>(); + + /** * Android package type */ diff --git a/src/main/java/net/geedge/asw/common/util/RCode.java b/src/main/java/net/geedge/asw/common/util/RCode.java index f2aed72..7cc834e 100644 --- a/src/main/java/net/geedge/asw/common/util/RCode.java +++ b/src/main/java/net/geedge/asw/common/util/RCode.java @@ -29,6 +29,7 @@ public enum RCode { SYS_ROLE_BUILT_IN(100017, "Built-in role are not allowed to delete or update"), SYS_ROLE_NOT_DELETE(100018, "Used role cannot be deleted"), SYS_USER_OLDPWD_INCORRECT(100019, "Incorrect old password. Please try again."), + SYS_SYSTEM_USER_NOT_LOGIN(100020, "System user cannot login."), // Application diff --git a/src/main/java/net/geedge/asw/module/environment/controller/EnvironmentController.java b/src/main/java/net/geedge/asw/module/environment/controller/EnvironmentController.java index 1212233..1b0ea07 100644 --- a/src/main/java/net/geedge/asw/module/environment/controller/EnvironmentController.java +++ b/src/main/java/net/geedge/asw/module/environment/controller/EnvironmentController.java @@ -169,25 +169,7 @@ public class EnvironmentController { @DeleteMapping("/{envId}/session/{sessionId}") @Transactional public R removeSession(@PathVariable("envId") String envId, @PathVariable("sessionId") String sessionId, @RequestParam String workspaceId) { - EnvironmentSessionEntity session = environmentSessionService.getById(sessionId); - WebSocketSession novncSession = Constants.ENV_NOVNC_WEBSOCKET_SESSION.get(sessionId); - WebSocketSession terminalSession = Constants.ENV_TERMINAL_WEBSOCKET_SESSION.get(sessionId); - // 根据 session 找到 novncSession&terminalSession ,更新状态,设置结束时间 - session.setEndTimestamp(System.currentTimeMillis()); - session.setStatus(2); - environmentSessionService.updateById(session); - try { - if (T.ObjectUtil.isNotEmpty(novncSession)) { - Constants.ENV_NOVNC_WEBSOCKET_SESSION.remove(sessionId); - novncSession.close(CloseStatus.NORMAL.withReason("Administrator disconnected.")); - } - if (T.ObjectUtil.isNotEmpty(terminalSession)) { - Constants.ENV_TERMINAL_WEBSOCKET_SESSION.remove(sessionId); - terminalSession.close(CloseStatus.NORMAL.withReason("Administrator disconnected.")); - } - } catch (IOException e) { - log.error(e, "RemoveSession send exit prompt error sessionId: {}", sessionId); - } + environmentService.removeSession(sessionId); return R.ok(); } diff --git a/src/main/java/net/geedge/asw/module/environment/service/IEnvironmentService.java b/src/main/java/net/geedge/asw/module/environment/service/IEnvironmentService.java index fb98195..69668da 100644 --- a/src/main/java/net/geedge/asw/module/environment/service/IEnvironmentService.java +++ b/src/main/java/net/geedge/asw/module/environment/service/IEnvironmentService.java @@ -22,4 +22,6 @@ public interface IEnvironmentService extends IService{ EnvironmentEntity saveEnv(EnvironmentEntity entity); EnvironmentEntity updateEnv(EnvironmentEntity entity); + + void removeSession(String sessionId); } diff --git a/src/main/java/net/geedge/asw/module/environment/service/impl/EnvironmentServiceImpl.java b/src/main/java/net/geedge/asw/module/environment/service/impl/EnvironmentServiceImpl.java index 0fd80ca..4ccc15f 100644 --- a/src/main/java/net/geedge/asw/module/environment/service/impl/EnvironmentServiceImpl.java +++ b/src/main/java/net/geedge/asw/module/environment/service/impl/EnvironmentServiceImpl.java @@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import net.geedge.asw.common.config.Query; import net.geedge.asw.common.util.ASWException; +import net.geedge.asw.common.util.Constants; import net.geedge.asw.common.util.RCode; import net.geedge.asw.common.util.T; import net.geedge.asw.module.attribute.entity.AttributeEntity; @@ -24,7 +25,10 @@ import net.geedge.asw.module.workspace.service.IWorkspaceService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.socket.CloseStatus; +import org.springframework.web.socket.WebSocketSession; +import java.io.IOException; import java.util.List; import java.util.Map; import java.util.function.Function; @@ -202,4 +206,27 @@ public class EnvironmentServiceImpl extends ServiceImpl startGetJobLogThread(job, environment)); break; case "error": - updateJobStatus(job, RunnerConstant.JobStatus.FAILED.getValue()); - if (!resultJobThreads.contains(id)){ - resultJobThreads.add(id); - getJobResult(job, environment); - } + Constants.RESULT_JOB_THREAD.computeIfAbsent(id, jobId -> startGetJobResultThread(job, environment, RunnerConstant.JobStatus.FAILED.getValue())); break; case "done": - updateJobStatus(job, RunnerConstant.JobStatus.PASSED.getValue()); - if (!resultJobThreads.contains(id)){ - resultJobThreads.add(id); - getJobResult(job, environment); - } + Constants.RESULT_JOB_THREAD.computeIfAbsent(id, jobId -> startGetJobResultThread(job, environment, RunnerConstant.JobStatus.PASSED.getValue())); break; } } @@ -137,24 +121,25 @@ public class JobPlaybookExecResultChecker extends QuartzJobBean { } } - private void startJobVirtualThread(JobEntity job, EnvironmentEntity environment) { - T.ThreadUtil.execAsync(() -> { + private Thread startGetJobLogThread(JobEntity job, EnvironmentEntity environment) { + Thread thread = Thread.ofVirtual().start(() -> { + log.info("[playbookExecResultChecker] [startGetJobLogThread] [begin] [job id: {}]", job.getId()); try { while (true) { if (isJobInRunningStatus(job)) { - if (log.isDebugEnabled()) { - log.debug("[playbookExecResultChecker] [Job status updated] [stopJobVirtualThread ] [job id: {}]", job.getId()); - } - runningJobThreads.remove(job.getId()); + Constants.RUNNING_JOB_THREAD.remove(job.getId()); + log.info("[playbookExecResultChecker] [startGetJobLogThread] [finshed ] [job id: {}]", job.getId()); break; } performJobLogic(job, environment); Thread.sleep(2000); // 每 2 秒执行一次 } } catch (InterruptedException e) { + Constants.RUNNING_JOB_THREAD.remove(job.getId()); Thread.currentThread().interrupt(); // 恢复中断状态 } }); + return thread; } // 检查 Job 的状态是否为 running @@ -165,13 +150,14 @@ public class JobPlaybookExecResultChecker extends QuartzJobBean { /** * 获取 playbook 执行日志 + * * @param job * @param environment */ private void performJobLogic(JobEntity job, EnvironmentEntity environment) { File logFile = T.FileUtil.file(job.getLogPath()); Integer offset = 0; - if (logFile.exists()){ + if (logFile.exists()) { offset = T.FileUtil.readBytes(logFile).length; } JSONObject paramJSONObject = environment.getParamJSONObject(); @@ -192,32 +178,28 @@ public class JobPlaybookExecResultChecker extends QuartzJobBean { if (T.ObjectUtil.equal(RCode.SUCCESS.getCode(), jsonObject.getInt("code"))) { JSONObject data = jsonObject.getJSONObject("data"); String content = data.getStr("content"); + content = T.StrUtil.nullToDefault(content, T.StrUtil.EMPTY); T.FileUtil.appendString(content, logFile, "UTF-8"); } } } - - @PreDestroy - public void shutdown() { - runningJobThreads.clear(); - resultJobThreads.clear(); - } - - /** * get pcap log + * * @param job - * @param value job status: error and done + * @param value job status: error and done * @param environment */ - private void getJobResult(JobEntity job, EnvironmentEntity environment) { - T.ThreadUtil.execAsync(() -> { + @Transactional(rollbackFor = Exception.class) + private Thread startGetJobResultThread(JobEntity job, EnvironmentEntity environment, String status) { + Thread thread = Thread.ofVirtual().start(() -> { File destination = null; File pcapDestination = null; InputStream inputStream = null; ZipFile zipFile = null; try { + log.info("[playbookExecResultChecker] [startGetJobResultThread] [job status] [jod id: {}]", status, job.getId()); JSONObject paramJSONObject = environment.getParamJSONObject(); String url = paramJSONObject.getStr("url"); String token = paramJSONObject.getStr("token"); @@ -225,8 +207,7 @@ public class JobPlaybookExecResultChecker extends QuartzJobBean { request.header("Authorization", token); HttpResponse response = request.execute(); - - log.info("[playbookExecResultChecker] [getJobResult] [jod id: {}] [request env api] [status: {}]", job.getId(), response.getStatus()); + log.info("[playbookExecResultChecker] [startGetJobResultThread] [request env playbook result api] [status: {}]", response.getStatus()); if (response.isOk()) { destination = T.FileUtil.file(Constants.TEMP_PATH, T.StrUtil.concat(true, job.getId(), ".zip")); @@ -236,6 +217,7 @@ public class JobPlaybookExecResultChecker extends QuartzJobBean { for (ZipEntry entry : list) { if (entry.getName().endsWith("pcap")) { PackageEntity packageEntity = packageService.getById(job.getPackageId()); + // pcap name {package.name}-job-{jobId[0:8]}.pcap String fileName = T.StrUtil.concat(true, packageEntity.getName(), T.StrUtil.DASHED, "job", T.StrUtil.DASHED, T.StrUtil.sub(job.getId(), 0, 8), ".pcap"); pcapDestination = T.FileUtil.file(Constants.TEMP_PATH, fileName); @@ -244,13 +226,8 @@ public class JobPlaybookExecResultChecker extends QuartzJobBean { Resource fileResource = new FileSystemResource(pcapDestination); // upload pcap file PcapEntity pcapEntity = pcapService.savePcap(fileResource, "", job.getWorkspaceId(), job.getCreateUserId()); - - if (log.isDebugEnabled()) { - log.debug("[playbookExecResultChecker] [getJobResult] [job id: {}]: {}] [upload pcap: {}]", job.getId(), T.JSONUtil.toJsonStr(pcapEntity)); - } - + log.info("[playbookExecResultChecker] [startGetJobResultThread] [upload pcap: {}] [job id: {}]: {}] ", T.JSONUtil.toJsonStr(pcapEntity), job.getId()); job.setPcapId(pcapEntity.getId()); - jobService.updateById(job); } else { // log inputStream = T.ZipUtil.get(zipFile, entry.getName()); @@ -259,23 +236,26 @@ public class JobPlaybookExecResultChecker extends QuartzJobBean { } } } + // update job status + job.setStatus(status); + job.setEndTimestamp(System.currentTimeMillis()); + jobService.updateById(job); + + // remove session + EnvironmentSessionEntity session = environmentSessionService.getOne(new LambdaQueryWrapper().eq(EnvironmentSessionEntity::getJobId, job.getId())); + environmentService.removeSession(session.getId()); + log.info("[playbookExecResultChecker] [startGetJobResultThread] [finshed] [job id: {}]", job.getId()); } catch (Exception e) { - log.error("[playbookExecResultChecker] [getJobResult] [error]", e); + log.error("[playbookExecResultChecker] [startGetJobResultThread] [error]", e); } finally { T.IoUtil.close(zipFile); T.FileUtil.del(destination); T.FileUtil.del(pcapDestination); T.IoUtil.close(inputStream); - resultJobThreads.remove(job.getId()); + Constants.RESULT_JOB_THREAD.remove(job.getId()); } }); - } - - private void updateJobStatus(JobEntity job, String value) { - log.info("[playbookExecResultChecker] [updateJobStatus] [jod id: {}] [status: {}]", job.getId(), value); - job.setStatus(value); - job.setEndTimestamp(System.currentTimeMillis()); - jobService.updateById(job); + return thread; } } diff --git a/src/main/java/net/geedge/asw/module/runner/job/JobPlaybookExecutor.java b/src/main/java/net/geedge/asw/module/runner/job/JobPlaybookExecutor.java index 5860318..8bddd32 100644 --- a/src/main/java/net/geedge/asw/module/runner/job/JobPlaybookExecutor.java +++ b/src/main/java/net/geedge/asw/module/runner/job/JobPlaybookExecutor.java @@ -12,7 +12,9 @@ import net.geedge.asw.common.util.T; import net.geedge.asw.module.app.entity.PackageEntity; import net.geedge.asw.module.app.service.IPackageService; import net.geedge.asw.module.environment.entity.EnvironmentEntity; +import net.geedge.asw.module.environment.entity.EnvironmentSessionEntity; import net.geedge.asw.module.environment.service.IEnvironmentService; +import net.geedge.asw.module.environment.service.IEnvironmentSessionService; import net.geedge.asw.module.runner.entity.JobEntity; import net.geedge.asw.module.runner.entity.PlaybookEntity; import net.geedge.asw.module.runner.service.IJobService; @@ -48,6 +50,9 @@ public class JobPlaybookExecutor extends QuartzJobBean { @Autowired private IPlaybookService playbookService; + @Autowired + private IEnvironmentSessionService environmentSessionService; + @Override protected void executeInternal(JobExecutionContext context) { Thread.currentThread().setName("JobPlaybookExecutor"); @@ -67,17 +72,20 @@ public class JobPlaybookExecutor extends QuartzJobBean { @Transactional(rollbackFor = Exception.class) public void playbookExecutor() { - List list = jobService.list(new LambdaQueryWrapper().eq(JobEntity::getStatus, RunnerConstant.JobStatus.CREATED.getValue())); - Map> jobByEnvList = list.stream().collect(Collectors.groupingBy(JobEntity::getEnvId)); + List createdList = jobService.list(new LambdaQueryWrapper().eq(JobEntity::getStatus, RunnerConstant.JobStatus.CREATED.getValue())); + Map> jobByEnvList = createdList.stream().collect(Collectors.groupingBy(JobEntity::getEnvId)); for (Map.Entry> jobByEnv : jobByEnvList.entrySet()) { String envId = jobByEnv.getKey(); List jobList = jobByEnv.getValue(); - Thread.ofVirtual().start(() -> { + T.ThreadUtil.execAsync(() -> { for (JobEntity job : jobList) { - List JobRunList = jobService.list(new LambdaQueryWrapper().eq(JobEntity::getStatus, RunnerConstant.JobStatus.RUNNING.getValue()).eq(JobEntity::getEnvId, envId)); + List JobRunList = jobService.list(new LambdaQueryWrapper() + .eq(JobEntity::getStatus, RunnerConstant.JobStatus.RUNNING.getValue()) + .eq(JobEntity::getEnvId, envId)); if (T.CollUtil.isNotEmpty(JobRunList)) { continue; } + EnvironmentEntity environment = environmentService.getById(envId); if (!environment.getStatus().equals(1)) { if (log.isDebugEnabled()) { @@ -86,40 +94,37 @@ public class JobPlaybookExecutor extends QuartzJobBean { continue; } - String playbookId = job.getPlaybookId(); - String packageId = job.getPackageId(); - PackageEntity packageEntity = packageService.getById(packageId); - File packageFile = T.FileUtil.file(packageEntity.getPath()); - String packageName = packageEntity.getIdentifier(); - PlaybookEntity playbook = playbookService.getById(playbookId); - File playbookFile = T.FileUtil.file(playbook.getPath()); + List sessionList = environmentSessionService.list(new LambdaQueryWrapper() + .eq(EnvironmentSessionEntity::getStatus, "1") + .eq(EnvironmentSessionEntity::getEnvId, envId)); + if (T.CollUtil.isNotEmpty(sessionList)) { + if (log.isDebugEnabled()) { + log.debug("[playbookExecutor] [environment is in used] [jobId: {}] [envId: {}]", job.getId(), environment.getId()); + } + continue; + } - log.info("[playbookExecutor] [jobId: {}] [envId: {}] [playbookId: {}] [packageId: {}]", job.getId(), environment.getId(), playbookId, packageId); + // update job status running + jobService.update(new LambdaUpdateWrapper() + .set(JobEntity::getStatus, RunnerConstant.JobStatus.RUNNING.getValue()) + .set(JobEntity::getStartTimestamp, System.currentTimeMillis()) + .eq(JobEntity::getId, job.getId()) + ); - JSONObject paramJSONObject = environment.getParamJSONObject(); - String url = paramJSONObject.getStr("url"); - String token = paramJSONObject.getStr("token"); + // add session + EnvironmentSessionEntity session = new EnvironmentSessionEntity(); + session.setEnvId(envId); + session.setJobId(job.getId()); + session.setStatus(1); + session.setUserId("system"); + session.setWorkspaceId(job.getWorkspaceId()); + session.setStartTimestamp(System.currentTimeMillis()); + environmentSessionService.save(session); - File zipFile = T.FileUtil.file(Constants.TEMP_PATH, T.StrUtil.concat(true, job.getId(), ".zip")); + HttpResponse response = requestEnvPlaybook(job, environment); + log.info("[playbookExecutor] [job id: {}] [env: {}] [status: {}]", job.getId(), environment.getId(), response.getStatus()); + if (!response.isOk()) { - HttpRequest request = T.HttpUtil.createPost(String.format("%s/api/v1/env/playbook", url)); - T.ZipUtil.zip(zipFile, true, packageFile, playbookFile); - request.form("file", zipFile); - request.form("id", job.getId()); - request.form("packageName", packageName); - request.header("Authorization", token); - - HttpResponse response = request.execute(); - log.info("[playbookExecutor] [env: {}] [status: {}]", environment.getId(), response.getStatus()); - if (response.isOk()) { - // update job status, starTime, updateTimestamp - jobService.update(new LambdaUpdateWrapper() - .set(JobEntity::getStatus, RunnerConstant.JobStatus.RUNNING.getValue()) - .set(JobEntity::getStartTimestamp, System.currentTimeMillis()) - .eq(JobEntity::getId, job.getId()) - ); - - }else { String result = response.body(); if (log.isDebugEnabled()) { log.debug("[playbookExecutor] [env: {}] [result: {}]", environment.getId(), result); @@ -132,7 +137,6 @@ public class JobPlaybookExecutor extends QuartzJobBean { // update job status, starTime, updateTimestamp jobService.update(new LambdaUpdateWrapper() .set(JobEntity::getStatus, RunnerConstant.JobStatus.FAILED.getValue()) - .set(JobEntity::getStartTimestamp, System.currentTimeMillis()) .set(JobEntity::getEndTimestamp, System.currentTimeMillis()) .eq(JobEntity::getId, job.getId())); } @@ -140,4 +144,32 @@ public class JobPlaybookExecutor extends QuartzJobBean { }); } } + + private HttpResponse requestEnvPlaybook(JobEntity job, EnvironmentEntity environment) { + String playbookId = job.getPlaybookId(); + String packageId = job.getPackageId(); + + PackageEntity packageEntity = packageService.getById(packageId); + File packageFile = T.FileUtil.file(packageEntity.getPath()); + String packageName = packageEntity.getIdentifier(); + + PlaybookEntity playbook = playbookService.getById(playbookId); + File playbookFile = T.FileUtil.file(playbook.getPath()); + + log.info("[playbookExecutor] [jobId: {}] [envId: {}] [playbookId: {}] [packageId: {}]", job.getId(), environment.getId(), playbookId, packageId); + JSONObject paramJSONObject = environment.getParamJSONObject(); + String url = paramJSONObject.getStr("url"); + String token = paramJSONObject.getStr("token"); + File zipFile = T.FileUtil.file(Constants.TEMP_PATH, T.StrUtil.concat(true, job.getId(), ".zip")); + + HttpRequest request = T.HttpUtil.createPost(String.format("%s/api/v1/env/playbook", url)); + T.ZipUtil.zip(zipFile, true, packageFile, playbookFile); + request.form("file", zipFile); + request.form("id", job.getId()); + request.form("packageName", packageName); + request.header("Authorization", token); + + HttpResponse response = request.execute(); + return response; + } } diff --git a/src/main/java/net/geedge/asw/module/runner/service/impl/JobServiceImpl.java b/src/main/java/net/geedge/asw/module/runner/service/impl/JobServiceImpl.java index 194114a..ff06638 100644 --- a/src/main/java/net/geedge/asw/module/runner/service/impl/JobServiceImpl.java +++ b/src/main/java/net/geedge/asw/module/runner/service/impl/JobServiceImpl.java @@ -2,6 +2,7 @@ package net.geedge.asw.module.runner.service.impl; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.log.Log; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -12,7 +13,9 @@ import net.geedge.asw.common.util.T; import net.geedge.asw.module.app.entity.PackageEntity; import net.geedge.asw.module.app.service.IPackageService; import net.geedge.asw.module.environment.entity.EnvironmentEntity; +import net.geedge.asw.module.environment.entity.EnvironmentSessionEntity; import net.geedge.asw.module.environment.service.IEnvironmentService; +import net.geedge.asw.module.environment.service.IEnvironmentSessionService; import net.geedge.asw.module.runner.dao.JobDao; import net.geedge.asw.module.runner.entity.JobEntity; import net.geedge.asw.module.runner.entity.PcapEntity; @@ -59,6 +62,9 @@ public class JobServiceImpl extends ServiceImpl implements IJ @Autowired private IWorkspaceService workspaceService; + @Autowired + private IEnvironmentSessionService environmentSessionService; + /** * rootPath/result/{jobId} @@ -95,6 +101,9 @@ public class JobServiceImpl extends ServiceImpl implements IJ WorkspaceEntity workspace = workspaceService.getById(job.getWorkspaceId()); job.setWorkspace(workspace); + EnvironmentSessionEntity session = environmentSessionService.getOne(new LambdaQueryWrapper().eq(EnvironmentSessionEntity::getJobId, id)); + job.setSession(session); + if (-1 == job.getStartTimestamp()) { job.setStartTimestamp(null); } diff --git a/src/main/java/net/geedge/asw/module/sys/service/impl/SysAuthServiceImpl.java b/src/main/java/net/geedge/asw/module/sys/service/impl/SysAuthServiceImpl.java index 2f938c1..71eb975 100644 --- a/src/main/java/net/geedge/asw/module/sys/service/impl/SysAuthServiceImpl.java +++ b/src/main/java/net/geedge/asw/module/sys/service/impl/SysAuthServiceImpl.java @@ -44,6 +44,9 @@ public class SysAuthServiceImpl implements ISysAuthService { @Override public SysUserEntity login(String userName, String pwd) { + if (T.StrUtil.equals(userName, "system")) { + throw ASWException.builder().rcode(RCode.SYS_SYSTEM_USER_NOT_LOGIN).build(); + } SysUserEntity userEntity = userDao .selectOne(new QueryWrapper().lambda().eq(SysUserEntity::getUserName, userName)); if (T.ObjectUtil.isNull(userEntity) diff --git a/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql b/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql index f63cb25..d235b8d 100644 --- a/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql +++ b/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql @@ -22,6 +22,7 @@ CREATE TABLE `sys_user` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 添加内置用户 INSERT INTO `sys_user`(`id`, `name`, `user_name`, `pwd`, `access_level`, `language`, `last_login_ip`, `last_login_timestamp`, `create_timestamp`, `update_timestamp`, `create_user_id`, `update_user_id`) VALUES ('admin', 'admin', 'admin', 'ad9d757e620d5d9cd8e32c3dbcf37525', 'administrator', 'en', '', UNIX_TIMESTAMP(NOW())*1000, UNIX_TIMESTAMP(NOW())*1000, UNIX_TIMESTAMP(NOW())*1000, 'admin', 'admin'); +INSERT INTO `sys_user`(`id`, `name`, `user_name`, `pwd`, `access_level`, `language`, `last_login_ip`, `last_login_timestamp`, `create_timestamp`, `update_timestamp`, `create_user_id`, `update_user_id`) VALUES ('system', 'system', 'system', 'ac45337abb5daec242e59aa5c9687', 'administrator', 'en', '', UNIX_TIMESTAMP(NOW())*1000, UNIX_TIMESTAMP(NOW())*1000, UNIX_TIMESTAMP(NOW())*1000, 'system', 'system'); /** * 1、新增 sys_role 表