mirror of
https://github.com/dataease/dataease.git
synced 2025-02-24 11:32:57 +08:00
perf: 社区版token机制
This commit is contained in:
parent
276d5043dd
commit
e755248d59
@ -5,14 +5,17 @@ import com.auth0.jwt.JWTCreator;
|
|||||||
import com.auth0.jwt.algorithms.Algorithm;
|
import com.auth0.jwt.algorithms.Algorithm;
|
||||||
import io.dataease.api.permissions.login.dto.PwdLoginDTO;
|
import io.dataease.api.permissions.login.dto.PwdLoginDTO;
|
||||||
import io.dataease.auth.bo.TokenUserBO;
|
import io.dataease.auth.bo.TokenUserBO;
|
||||||
|
import io.dataease.auth.config.SubstituleLoginConfig;
|
||||||
import io.dataease.auth.vo.TokenVO;
|
import io.dataease.auth.vo.TokenVO;
|
||||||
|
import io.dataease.exception.DEException;
|
||||||
|
import io.dataease.i18n.Translator;
|
||||||
import io.dataease.utils.LogUtil;
|
import io.dataease.utils.LogUtil;
|
||||||
|
import io.dataease.utils.Md5Utils;
|
||||||
|
import io.dataease.utils.RsaUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@ConditionalOnMissingBean(name = "loginServer")
|
@ConditionalOnMissingBean(name = "loginServer")
|
||||||
@ -21,11 +24,26 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
public class SubstituleLoginServer {
|
public class SubstituleLoginServer {
|
||||||
|
|
||||||
@PostMapping("/login/localLogin")
|
@PostMapping("/login/localLogin")
|
||||||
public TokenVO localLogin(PwdLoginDTO dto) {
|
public TokenVO localLogin(@RequestBody PwdLoginDTO dto) {
|
||||||
|
|
||||||
|
String name = dto.getName();
|
||||||
|
name = RsaUtils.decryptStr(name);
|
||||||
|
String pwd = dto.getPwd();
|
||||||
|
pwd = RsaUtils.decryptStr(pwd);
|
||||||
|
|
||||||
|
dto.setName(name);
|
||||||
|
dto.setPwd(pwd);
|
||||||
|
|
||||||
|
if (!StringUtils.equals("admin", name)) {
|
||||||
|
DEException.throwException("仅admin账号可用");
|
||||||
|
}
|
||||||
|
if (!StringUtils.equals(pwd, SubstituleLoginConfig.getPwd())) {
|
||||||
|
DEException.throwException(Translator.get("i18n_login_name_pwd_err"));
|
||||||
|
}
|
||||||
TokenUserBO tokenUserBO = new TokenUserBO();
|
TokenUserBO tokenUserBO = new TokenUserBO();
|
||||||
tokenUserBO.setUserId(1L);
|
tokenUserBO.setUserId(1L);
|
||||||
tokenUserBO.setDefaultOid(1L);
|
tokenUserBO.setDefaultOid(1L);
|
||||||
String md5Pwd = "83d923c9f1d8fcaa46cae0ed2aaa81b5";
|
String md5Pwd = Md5Utils.md5(pwd);
|
||||||
return generate(tokenUserBO, md5Pwd);
|
return generate(tokenUserBO, md5Pwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
de-xpack
2
de-xpack
@ -1 +1 @@
|
|||||||
Subproject commit f028be49a62cb21a53c11fa4f931946417381a55
|
Subproject commit 1aae01674cc0dd042bbb5eac7f1cc54f30b9d23d
|
@ -0,0 +1,71 @@
|
|||||||
|
package io.dataease.auth.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import io.dataease.utils.CommonBeanFactory;
|
||||||
|
import io.dataease.utils.LogUtil;
|
||||||
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ConditionalOnMissingBean(name = "loginServer")
|
||||||
|
@Configuration
|
||||||
|
public class SubstituleLoginConfig {
|
||||||
|
|
||||||
|
|
||||||
|
private static String jsonFilePath = "classpath:substitule.json";
|
||||||
|
|
||||||
|
private static String pwd;
|
||||||
|
|
||||||
|
private static boolean ready = false;
|
||||||
|
|
||||||
|
|
||||||
|
@ConditionalOnMissingBean(name = "loginServer")
|
||||||
|
@Bean
|
||||||
|
public Map<String, Object> substituleLoginData(ResourceLoader resourceLoader) throws IOException {
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
File jsonFile = new File(jsonFilePath);
|
||||||
|
if (!jsonFile.exists()) {
|
||||||
|
pwd = CommonBeanFactory.getBean(Environment.class).getProperty("dataease.default-pwd", "DataEase@123456");
|
||||||
|
modifyPwd(pwd);
|
||||||
|
}
|
||||||
|
return objectMapper.readValue(jsonFile, Map.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getPwd() {
|
||||||
|
if (!ready) {
|
||||||
|
ready = true;
|
||||||
|
Object substituleLoginDataObject = CommonBeanFactory.getBean("substituleLoginData");
|
||||||
|
if (substituleLoginDataObject != null) {
|
||||||
|
Map<String, Object> substituleLoginData = (Map<String, Object>) substituleLoginDataObject;
|
||||||
|
if (ObjectUtils.isNotEmpty(substituleLoginData.get("pwd"))) {
|
||||||
|
pwd = substituleLoginData.get("pwd").toString();
|
||||||
|
return substituleLoginData.get("pwd").toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void modifyPwd(String pwd) {
|
||||||
|
File file = new File(jsonFilePath);
|
||||||
|
Map<String, String> myObject = new HashMap<>();
|
||||||
|
myObject.put("pwd", pwd);
|
||||||
|
SubstituleLoginConfig.pwd = pwd;
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
try (FileOutputStream fos = new FileOutputStream(file)) {
|
||||||
|
// 将对象写入文件
|
||||||
|
mapper.writeValue(fos, myObject);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LogUtil.error(e.getCause(), new Throwable(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,13 +6,22 @@ import io.dataease.utils.*;
|
|||||||
import jakarta.servlet.FilterConfig;
|
import jakarta.servlet.FilterConfig;
|
||||||
import jakarta.servlet.*;
|
import jakarta.servlet.*;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.HttpStatusCode;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class TokenFilter implements Filter {
|
public class TokenFilter implements Filter {
|
||||||
|
|
||||||
|
private static final String headName = "DE-GATEWAY-FLAG";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(FilterConfig filterConfig) throws ServletException {
|
public void init(FilterConfig filterConfig) throws ServletException {
|
||||||
}
|
}
|
||||||
@ -36,10 +45,6 @@ public class TokenFilter implements Filter {
|
|||||||
filterChain.doFilter(servletRequest, servletResponse);
|
filterChain.doFilter(servletRequest, servletResponse);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/*String refreshToken = null;
|
|
||||||
if (StringUtils.isNotBlank(refreshToken = ServletUtils.request().getHeader(AuthConstant.REFRESH_TOKEN_KEY))) {
|
|
||||||
ServletUtils.response().addHeader(AuthConstant.REFRESH_TOKEN_KEY, refreshToken);
|
|
||||||
}*/
|
|
||||||
String executeVersion = null;
|
String executeVersion = null;
|
||||||
if (StringUtils.isNotBlank(executeVersion = VersionUtil.getRandomVersion())) {
|
if (StringUtils.isNotBlank(executeVersion = VersionUtil.getRandomVersion())) {
|
||||||
Objects.requireNonNull(ServletUtils.response()).addHeader(AuthConstant.DE_EXECUTE_VERSION, executeVersion);
|
Objects.requireNonNull(ServletUtils.response()).addHeader(AuthConstant.DE_EXECUTE_VERSION, executeVersion);
|
||||||
@ -52,12 +57,41 @@ public class TokenFilter implements Filter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String token = ServletUtils.getToken();
|
String token = ServletUtils.getToken();
|
||||||
TokenUserBO userBO = TokenUtils.validate(token);
|
TokenUserBO userBO = null;
|
||||||
|
try {
|
||||||
|
userBO = TokenUtils.validate(token);
|
||||||
UserUtils.setUserInfo(userBO);
|
UserUtils.setUserInfo(userBO);
|
||||||
|
} catch (Exception e) {
|
||||||
|
HttpServletResponse res = (HttpServletResponse) servletResponse;
|
||||||
|
LogUtil.error(e.getMessage(), e);
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
String msg = URLEncoder.encode(e.getMessage(), StandardCharsets.UTF_8).replace("+", "%20");
|
||||||
|
headers.add(headName, msg);
|
||||||
|
sendResponseEntity(res, new ResponseEntity<>(e.getMessage(), headers, HttpStatus.UNAUTHORIZED));
|
||||||
|
return;
|
||||||
|
}
|
||||||
filterChain.doFilter(servletRequest, servletResponse);
|
filterChain.doFilter(servletRequest, servletResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendResponseEntity(HttpServletResponse httpResponse, ResponseEntity<String> responseEntity) throws IOException {
|
||||||
|
HttpHeaders headers = responseEntity.getHeaders();
|
||||||
|
HttpStatusCode statusCode = responseEntity.getStatusCode();
|
||||||
|
|
||||||
|
// 设置状态码
|
||||||
|
httpResponse.setStatus(statusCode.value());
|
||||||
|
|
||||||
|
// 设置响应头
|
||||||
|
if (headers != null) {
|
||||||
|
for (String name : headers.keySet()) {
|
||||||
|
httpResponse.setHeader(name, headers.getFirst(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置响应体
|
||||||
|
httpResponse.getWriter().write(responseEntity.getBody());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,19 @@
|
|||||||
package io.dataease.utils;
|
package io.dataease.utils;
|
||||||
|
|
||||||
import com.auth0.jwt.JWT;
|
import com.auth0.jwt.JWT;
|
||||||
|
import com.auth0.jwt.JWTVerifier;
|
||||||
|
import com.auth0.jwt.algorithms.Algorithm;
|
||||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||||
|
import com.auth0.jwt.interfaces.Verification;
|
||||||
import io.dataease.auth.bo.TokenUserBO;
|
import io.dataease.auth.bo.TokenUserBO;
|
||||||
|
import io.dataease.auth.config.SubstituleLoginConfig;
|
||||||
import io.dataease.exception.DEException;
|
import io.dataease.exception.DEException;
|
||||||
|
import io.dataease.license.utils.LicenseUtil;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
public class TokenUtils {
|
public class TokenUtils {
|
||||||
|
|
||||||
@ -28,8 +36,32 @@ public class TokenUtils {
|
|||||||
if (StringUtils.length(token) < 100) {
|
if (StringUtils.length(token) < 100) {
|
||||||
DEException.throwException("token is invalid");
|
DEException.throwException("token is invalid");
|
||||||
}
|
}
|
||||||
return userBOByToken(token);
|
TokenUserBO userBO = userBOByToken(token);
|
||||||
|
if (ObjectUtils.isEmpty(userBO) || LicenseUtil.licenseValid()) {
|
||||||
|
return userBO;
|
||||||
}
|
}
|
||||||
|
Long userId = userBO.getUserId();
|
||||||
|
String secret = null;
|
||||||
|
if (ObjectUtils.isEmpty(CommonBeanFactory.getBean("loginServer"))) {
|
||||||
|
String pwd = SubstituleLoginConfig.getPwd();
|
||||||
|
secret = Md5Utils.md5(pwd);
|
||||||
|
} else {
|
||||||
|
Object apisixTokenManage = CommonBeanFactory.getBean("apisixTokenManage");
|
||||||
|
Method method = DeReflectUtil.findMethod(apisixTokenManage.getClass(), "userCacheBO");
|
||||||
|
Object o = ReflectionUtils.invokeMethod(method, apisixTokenManage, userId);
|
||||||
|
Method pwdMethod = DeReflectUtil.findMethod(o.getClass(), "getPwd");
|
||||||
|
Object pwdObj = ReflectionUtils.invokeMethod(pwdMethod, o);
|
||||||
|
secret = pwdObj.toString();
|
||||||
|
}
|
||||||
|
Algorithm algorithm = Algorithm.HMAC256(secret);
|
||||||
|
Verification verification = JWT.require(algorithm).withClaim("uid", userId).withClaim("oid", userBO.getDefaultOid());
|
||||||
|
JWTVerifier verifier = verification.build();
|
||||||
|
DecodedJWT decode = JWT.decode(token);
|
||||||
|
algorithm.verify(decode);
|
||||||
|
verifier.verify(token);
|
||||||
|
return userBO;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static TokenUserBO validateLinkToken(String linkToken) {
|
public static TokenUserBO validateLinkToken(String linkToken) {
|
||||||
if (StringUtils.isBlank(linkToken)) {
|
if (StringUtils.isBlank(linkToken)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user