feat: 集成 satoken jwt
1. 登录成功后返回 jwt token
This commit is contained in:
8
pom.xml
8
pom.xml
@@ -79,6 +79,14 @@
|
|||||||
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||||
<version>1.37.0</version>
|
<version>1.37.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Sa-Token 整合 jwt -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.dev33</groupId>
|
||||||
|
<artifactId>sa-token-jwt</artifactId>
|
||||||
|
<version>1.37.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
|
|||||||
@@ -1,17 +1,23 @@
|
|||||||
package net.geedge.asw.common.config;
|
package net.geedge.asw.common.config;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import cn.dev33.satoken.config.SaTokenConfig;
|
||||||
|
import cn.dev33.satoken.interceptor.SaInterceptor;
|
||||||
|
import cn.dev33.satoken.jwt.SaJwtTemplate;
|
||||||
|
import cn.dev33.satoken.jwt.SaJwtUtil;
|
||||||
|
import cn.dev33.satoken.jwt.StpLogicJwtForStateless;
|
||||||
|
import cn.dev33.satoken.router.SaRouter;
|
||||||
|
import cn.dev33.satoken.stp.StpLogic;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.hutool.jwt.JWT;
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
import cn.dev33.satoken.config.SaTokenConfig;
|
import java.util.concurrent.TimeUnit;
|
||||||
import cn.dev33.satoken.interceptor.SaInterceptor;
|
|
||||||
import cn.dev33.satoken.router.SaRouter;
|
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
public class SaTokenConfigure implements WebMvcConfigurer {
|
public class SaTokenConfigure implements WebMvcConfigurer {
|
||||||
@@ -38,6 +44,8 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
|||||||
config.setTokenStyle("simple-uuid"); // token 风格
|
config.setTokenStyle("simple-uuid"); // token 风格
|
||||||
config.setIsLog(false); // 是否输出操作日志
|
config.setIsLog(false); // 是否输出操作日志
|
||||||
config.setIsPrint(false);
|
config.setIsPrint(false);
|
||||||
|
// jwt秘钥
|
||||||
|
config.setJwtSecretKey("ypCLARItfzxvdVqRwPcwIasdgAkhoubj");
|
||||||
// config.setIsReadCookie(false);
|
// config.setIsReadCookie(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,4 +58,29 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
|||||||
SaRouter.match("/api/v1/**").notMatch("/api/v1/login").check(r -> StpUtil.checkLogin());
|
SaRouter.match("/api/v1/**").notMatch("/api/v1/login").check(r -> StpUtil.checkLogin());
|
||||||
})).addPathPatterns("/**");
|
})).addPathPatterns("/**");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public StpLogic getStpLogicJwt() {
|
||||||
|
// Sa-Token 整合 jwt (Stateless 无状态模式)
|
||||||
|
return new StpLogicJwtForStateless();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义 SaJwtUtil 生成 token 的算法
|
||||||
|
*/
|
||||||
|
@PostConstruct
|
||||||
|
public void setSaJwtTemplate() {
|
||||||
|
SaJwtUtil.setSaJwtTemplate(new SaJwtTemplate() {
|
||||||
|
@Override
|
||||||
|
public String generateToken(JWT jwt, String keyt) {
|
||||||
|
// header
|
||||||
|
jwt.setHeader("alg", "HS256");
|
||||||
|
jwt.setHeader("typ", "JWT");
|
||||||
|
|
||||||
|
// payload
|
||||||
|
jwt.setPayload("iss", "net.geedge.asw");
|
||||||
|
return super.generateToken(jwt, keyt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import net.geedge.asw.module.app.entity.ApplicationEntity;
|
import net.geedge.asw.module.app.entity.ApplicationEntity;
|
||||||
import net.geedge.asw.module.app.entity.PackageEntity;
|
import net.geedge.asw.module.app.entity.PackageEntity;
|
||||||
|
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@TableName("pcap")
|
@TableName("pcap")
|
||||||
@@ -25,6 +26,9 @@ public class PcapEntity {
|
|||||||
private String createUserId;
|
private String createUserId;
|
||||||
private String workspaceId;
|
private String workspaceId;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private WorkspaceEntity workspace;
|
||||||
|
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
private String jobId;
|
private String jobId;
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ import net.geedge.asw.module.runner.util.PcapParserThread;
|
|||||||
import net.geedge.asw.module.runner.util.RunnerConstant;
|
import net.geedge.asw.module.runner.util.RunnerConstant;
|
||||||
import net.geedge.asw.module.workbook.service.IWorkbookResourceService;
|
import net.geedge.asw.module.workbook.service.IWorkbookResourceService;
|
||||||
import net.geedge.asw.module.workbook.util.WorkbookConstant;
|
import net.geedge.asw.module.workbook.util.WorkbookConstant;
|
||||||
|
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
|
||||||
|
import net.geedge.asw.module.workspace.service.IWorkspaceService;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
@@ -64,6 +66,9 @@ public class PcapServiceImpl extends ServiceImpl<PcapDao, PcapEntity> implements
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IWorkbookResourceService workbookResourceService;
|
private IWorkbookResourceService workbookResourceService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IWorkspaceService workspaceService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PcapEntity queryInfo(String id) {
|
public PcapEntity queryInfo(String id) {
|
||||||
PcapEntity pcap = this.getById(id);
|
PcapEntity pcap = this.getById(id);
|
||||||
@@ -180,6 +185,9 @@ public class PcapServiceImpl extends ServiceImpl<PcapDao, PcapEntity> implements
|
|||||||
for (String id : ids) {
|
for (String id : ids) {
|
||||||
PcapEntity pcapEntity = this.getById(id);
|
PcapEntity pcapEntity = this.getById(id);
|
||||||
if (T.ObjectUtil.isNotNull(pcapEntity)) {
|
if (T.ObjectUtil.isNotNull(pcapEntity)) {
|
||||||
|
WorkspaceEntity workspace = workspaceService.getById(pcapEntity.getWorkspaceId());
|
||||||
|
pcapEntity.setWorkspace(workspace);
|
||||||
|
|
||||||
PcapParserThread pcapParserThread = new PcapParserThread();
|
PcapParserThread pcapParserThread = new PcapParserThread();
|
||||||
pcapParserThread.setPcapEntity(pcapEntity);
|
pcapParserThread.setPcapEntity(pcapEntity);
|
||||||
taskList.add(pcapParserThread);
|
taskList.add(pcapParserThread);
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import org.opensearch.client.opensearch.core.BulkRequest;
|
|||||||
import org.opensearch.client.opensearch.core.BulkResponse;
|
import org.opensearch.client.opensearch.core.BulkResponse;
|
||||||
import org.opensearch.client.opensearch.core.bulk.BulkResponseItem;
|
import org.opensearch.client.opensearch.core.bulk.BulkResponseItem;
|
||||||
import org.opensearch.client.opensearch.indices.CreateIndexRequest;
|
import org.opensearch.client.opensearch.indices.CreateIndexRequest;
|
||||||
import org.opensearch.client.opensearch.indices.DeleteIndexRequest;
|
|
||||||
import org.opensearch.client.opensearch.indices.ExistsRequest;
|
import org.opensearch.client.opensearch.indices.ExistsRequest;
|
||||||
import org.opensearch.client.opensearch.indices.IndexSettings;
|
import org.opensearch.client.opensearch.indices.IndexSettings;
|
||||||
|
|
||||||
@@ -153,10 +152,8 @@ public class PcapParserThread implements Runnable {
|
|||||||
* @param jsonArray
|
* @param jsonArray
|
||||||
*/
|
*/
|
||||||
private void uploadToOpenSearch(JSONArray jsonArray) {
|
private void uploadToOpenSearch(JSONArray jsonArray) {
|
||||||
String pcapPath = pcapEntity.getPath();
|
String workspaceName = pcapEntity.getWorkspace().getName();
|
||||||
String md5Hex = T.DigestUtil.md5Hex(T.FileUtil.file(pcapPath));
|
String indexName = String.format("workspace-%s", workspaceName);
|
||||||
String indexName = String.format("session-%s", md5Hex);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// check if index exists
|
// check if index exists
|
||||||
boolean indexExists = openSearchClient.indices()
|
boolean indexExists = openSearchClient.indices()
|
||||||
@@ -165,25 +162,23 @@ public class PcapParserThread implements Runnable {
|
|||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("[uploadToOpenSearch] [index: {}] [exists: {}]", indexName, indexExists);
|
log.debug("[uploadToOpenSearch] [index: {}] [exists: {}]", indexName, indexExists);
|
||||||
}
|
}
|
||||||
// if index exists, delete
|
// if index not exists, create index with default settings
|
||||||
if (indexExists) {
|
if (!indexExists) {
|
||||||
openSearchClient.indices().delete(new DeleteIndexRequest.Builder().index(indexName).build());
|
|
||||||
log.debug("[uploadToOpenSearch] [index: {}] [deleted]", indexName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create index with default settings
|
|
||||||
openSearchClient.indices().create(
|
openSearchClient.indices().create(
|
||||||
new CreateIndexRequest.Builder()
|
new CreateIndexRequest.Builder()
|
||||||
.index(indexName)
|
.index(indexName)
|
||||||
.settings(new IndexSettings.Builder().build())
|
.settings(new IndexSettings.Builder().build())
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
|
log.debug("[uploadToOpenSearch] [index: {}] [created]", indexName);
|
||||||
|
}
|
||||||
|
|
||||||
// upload data in bulk
|
// upload data in bulk
|
||||||
BulkRequest.Builder br = new BulkRequest.Builder();
|
BulkRequest.Builder br = new BulkRequest.Builder();
|
||||||
|
String pcapId = pcapEntity.getId();
|
||||||
for (int i = 0; i < jsonArray.size(); i++) {
|
for (int i = 0; i < jsonArray.size(); i++) {
|
||||||
JSONObject jsonObject = (JSONObject) jsonArray.get(i);
|
JSONObject jsonObject = (JSONObject) jsonArray.get(i);
|
||||||
String id = String.valueOf(i);
|
String id = pcapId + "-" + String.valueOf(i);
|
||||||
br.operations(op -> op.index(
|
br.operations(op -> op.index(
|
||||||
idx -> idx.index(indexName)
|
idx -> idx.index(indexName)
|
||||||
.id(id)
|
.id(id)
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
package net.geedge.asw.module.sys.controller;
|
package net.geedge.asw.module.sys.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.config.SaTokenConfig;
|
||||||
import cn.dev33.satoken.stp.SaTokenInfo;
|
import cn.dev33.satoken.stp.SaTokenInfo;
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.hutool.jwt.JWT;
|
||||||
|
import cn.hutool.jwt.JWTUtil;
|
||||||
|
import cn.hutool.jwt.signers.JWTSignerUtil;
|
||||||
import net.geedge.asw.common.util.R;
|
import net.geedge.asw.common.util.R;
|
||||||
import net.geedge.asw.common.util.RCode;
|
import net.geedge.asw.common.util.RCode;
|
||||||
import net.geedge.asw.common.util.T;
|
import net.geedge.asw.common.util.T;
|
||||||
@@ -10,7 +14,9 @@ import net.geedge.asw.module.sys.service.ISysAuthService;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1")
|
@RequestMapping("/api/v1")
|
||||||
@@ -19,6 +25,9 @@ public class SysAuthController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ISysAuthService authService;
|
private ISysAuthService authService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SaTokenConfig saTokenConfig;
|
||||||
|
|
||||||
record AuthRecord(String userName, String pwd) {}
|
record AuthRecord(String userName, String pwd) {}
|
||||||
|
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
@@ -27,6 +36,29 @@ public class SysAuthController {
|
|||||||
.notEmpty(RCode.SYS_USER_PWD_ERROR);
|
.notEmpty(RCode.SYS_USER_PWD_ERROR);
|
||||||
SysUserEntity userEntity = authService.login(record.userName(), record.pwd());
|
SysUserEntity userEntity = authService.login(record.userName(), record.pwd());
|
||||||
SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
|
SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
|
||||||
|
|
||||||
|
String tokenValue = tokenInfo.getTokenValue();
|
||||||
|
|
||||||
|
JWT jwt = JWTUtil.parseToken(tokenValue);
|
||||||
|
|
||||||
|
// payload
|
||||||
|
jwt.setPayload("sub", userEntity.getUserName());
|
||||||
|
|
||||||
|
Map<String, Object> permissions = authService.userPermissions();
|
||||||
|
|
||||||
|
String roles = ((List<String>) T.JSONUtil.getByPath(T.JSONUtil.parse(permissions), "records.role.name")).stream()
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.joining(","));
|
||||||
|
jwt.setPayload("roles", roles);
|
||||||
|
|
||||||
|
Long eff = Long.valueOf(jwt.getPayload("eff").toString());
|
||||||
|
jwt.setPayload("exp", eff == -1L ? -1 : (eff / 1000));
|
||||||
|
jwt.setPayload("iat", System.currentTimeMillis() / 1000);
|
||||||
|
jwt.setPayload("nbf", System.currentTimeMillis() / 1000);
|
||||||
|
|
||||||
|
String sign = jwt.sign(JWTSignerUtil.hs256(saTokenConfig.getJwtSecretKey().getBytes()));
|
||||||
|
tokenInfo.setTokenValue(sign);
|
||||||
|
|
||||||
userEntity.setPwd(null);
|
userEntity.setPwd(null);
|
||||||
return R.ok().putData("tokenInfo", tokenInfo).putData("user", userEntity);
|
return R.ok().putData("tokenInfo", tokenInfo).putData("user", userEntity);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user