diff --git a/auth/api/src/main/java/com/tencent/supersonic/auth/api/authentication/adaptor/UserAdaptor.java b/auth/api/src/main/java/com/tencent/supersonic/auth/api/authentication/adaptor/UserAdaptor.java index f9254640c..f080a666d 100644 --- a/auth/api/src/main/java/com/tencent/supersonic/auth/api/authentication/adaptor/UserAdaptor.java +++ b/auth/api/src/main/java/com/tencent/supersonic/auth/api/authentication/adaptor/UserAdaptor.java @@ -6,6 +6,7 @@ import com.tencent.supersonic.auth.api.authentication.request.UserReq; import java.util.List; import java.util.Set; +import javax.servlet.http.HttpServletRequest; /** * UserAdaptor defines some interfaces for obtaining user and organization information @@ -20,7 +21,7 @@ public interface UserAdaptor { void register(UserReq userReq); - String login(UserReq userReq); + String login(UserReq userReq, HttpServletRequest request); List getUserByOrg(String key); diff --git a/auth/api/src/main/java/com/tencent/supersonic/auth/api/authentication/config/AuthenticationConfig.java b/auth/api/src/main/java/com/tencent/supersonic/auth/api/authentication/config/AuthenticationConfig.java index 2f5a9600e..f1a9db1fa 100644 --- a/auth/api/src/main/java/com/tencent/supersonic/auth/api/authentication/config/AuthenticationConfig.java +++ b/auth/api/src/main/java/com/tencent/supersonic/auth/api/authentication/config/AuthenticationConfig.java @@ -1,6 +1,9 @@ package com.tencent.supersonic.auth.api.authentication.config; +import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; @@ -18,12 +21,18 @@ public class AuthenticationConfig { @Value("${authentication.enable:false}") private boolean enabled; - @Value("${authentication.token.secret:secret}") - private String tokenSecret; + @Value("${authentication.token.default.appKey:supersonic}") + private String tokenDefaultAppKey; + + @Value("${authentication.token.appSecret:supersonic:secret}") + private String tokenAppSecret; @Value("${authentication.token.http.header.key:Authorization}") private String tokenHttpHeaderKey; + @Value("${authentication.token.http.app.key:App-Key}") + private String tokenHttpHeaderAppKey; + @Value("${authentication.app.appId:appId}") private String appId; @@ -35,4 +44,10 @@ public class AuthenticationConfig { @Value("${authentication.token.timeout:7200000}") private Long tokenTimeout; + + public Map getAppKeyToSecretMap() { + return Arrays.stream(this.tokenAppSecret.split(",")) + .map(s -> s.split(":")) + .collect(Collectors.toMap(e -> e[0].trim(), e -> e[1].trim())); + } } diff --git a/auth/api/src/main/java/com/tencent/supersonic/auth/api/authentication/service/UserService.java b/auth/api/src/main/java/com/tencent/supersonic/auth/api/authentication/service/UserService.java index 09254ccb1..dac5728b7 100644 --- a/auth/api/src/main/java/com/tencent/supersonic/auth/api/authentication/service/UserService.java +++ b/auth/api/src/main/java/com/tencent/supersonic/auth/api/authentication/service/UserService.java @@ -19,7 +19,7 @@ public interface UserService { void register(UserReq userCmd); - String login(UserReq userCmd); + String login(UserReq userCmd, HttpServletRequest request); Set getUserAllOrgId(String userName); diff --git a/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/adaptor/DefaultUserAdaptor.java b/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/adaptor/DefaultUserAdaptor.java index 54b423ad6..b3e9a7522 100644 --- a/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/adaptor/DefaultUserAdaptor.java +++ b/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/adaptor/DefaultUserAdaptor.java @@ -12,6 +12,7 @@ import com.tencent.supersonic.auth.authentication.persistence.repository.UserRep import com.tencent.supersonic.auth.authentication.utils.AESEncryptionUtil; import com.tencent.supersonic.auth.authentication.utils.UserTokenUtils; import com.tencent.supersonic.common.util.ContextUtils; +import javax.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import java.util.List; @@ -87,7 +88,7 @@ public class DefaultUserAdaptor implements UserAdaptor { } @Override - public String login(UserReq userReq) { + public String login(UserReq userReq, HttpServletRequest request) { UserTokenUtils userTokenUtils = ContextUtils.getBean(UserTokenUtils.class); UserDO userDO = getUser(userReq.getName()); if (userDO == null) { @@ -100,7 +101,7 @@ public class DefaultUserAdaptor implements UserAdaptor { if (userDO.getPassword().equals(password)) { UserWithPassword user = UserWithPassword.get(userDO.getId(), userDO.getName(), userDO.getDisplayName(), userDO.getEmail(), userDO.getPassword(), userDO.getIsAdmin()); - return userTokenUtils.generateToken(user); + return userTokenUtils.generateToken(user, request); } else { throw new RuntimeException("password not correct, please try again"); } diff --git a/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/interceptor/DefaultAuthenticationInterceptor.java b/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/interceptor/DefaultAuthenticationInterceptor.java index f38f3b4ec..07ffdb9ed 100644 --- a/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/interceptor/DefaultAuthenticationInterceptor.java +++ b/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/interceptor/DefaultAuthenticationInterceptor.java @@ -66,7 +66,7 @@ public class DefaultAuthenticationInterceptor extends AuthenticationInterceptor } private void setFakerUser(HttpServletRequest request) { - String token = userTokenUtils.generateAdminToken(); + String token = userTokenUtils.generateAdminToken(request); reflectSetparam(request, authenticationConfig.getTokenHttpHeaderKey(), token); setContext(User.getFakeUser().getName(), request); } diff --git a/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/rest/UserController.java b/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/rest/UserController.java index 4a86e92e0..b56635ba4 100644 --- a/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/rest/UserController.java +++ b/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/rest/UserController.java @@ -65,8 +65,8 @@ public class UserController { } @PostMapping("/login") - public String login(@RequestBody UserReq userCmd) { - return userService.login(userCmd); + public String login(@RequestBody UserReq userCmd, HttpServletRequest request) { + return userService.login(userCmd, request); } } diff --git a/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/service/UserServiceImpl.java b/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/service/UserServiceImpl.java index ee41ff8d8..013dcc504 100644 --- a/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/service/UserServiceImpl.java +++ b/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/service/UserServiceImpl.java @@ -68,8 +68,8 @@ public class UserServiceImpl implements UserService { } @Override - public String login(UserReq userReq) { - return ComponentFactory.getUserAdaptor().login(userReq); + public String login(UserReq userReq, HttpServletRequest request) { + return ComponentFactory.getUserAdaptor().login(userReq, request); } } diff --git a/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/utils/UserTokenUtils.java b/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/utils/UserTokenUtils.java index f1a47781e..e9c33790c 100644 --- a/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/utils/UserTokenUtils.java +++ b/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/utils/UserTokenUtils.java @@ -36,7 +36,7 @@ public class UserTokenUtils { this.authenticationConfig = authenticationConfig; } - public String generateToken(UserWithPassword user) { + public String generateToken(UserWithPassword user, HttpServletRequest request) { Map claims = new HashMap<>(5); claims.put(TOKEN_USER_ID, user.getId()); claims.put(TOKEN_USER_NAME, StringUtils.isEmpty(user.getName()) ? "" : user.getName()); @@ -44,22 +44,23 @@ public class UserTokenUtils { claims.put(TOKEN_USER_DISPLAY_NAME, user.getDisplayName()); claims.put(TOKEN_CREATE_TIME, System.currentTimeMillis()); claims.put(TOKEN_IS_ADMIN, user.getIsAdmin()); - return generate(claims); + String appKey = getAppKey(request); + return generate(claims, appKey); } - public String generateAdminToken() { + public String generateAdminToken(HttpServletRequest request) { UserWithPassword admin = new UserWithPassword("admin"); admin.setId(1L); admin.setName("admin"); admin.setPassword("admin"); admin.setDisplayName("admin"); admin.setIsAdmin(1); - return generateToken(admin); + return generateToken(admin, request); } public User getUser(HttpServletRequest request) { String token = request.getHeader(authenticationConfig.getTokenHttpHeaderKey()); - final Claims claims = getClaims(token); + final Claims claims = getClaims(token, request); Long userId = Long.parseLong(claims.getOrDefault(TOKEN_USER_ID, 0).toString()); String userName = String.valueOf(claims.get(TOKEN_USER_NAME)); String email = String.valueOf(claims.get(TOKEN_USER_EMAIL)); @@ -76,7 +77,7 @@ public class UserTokenUtils { log.warn("{}, uri: {}", message, request.getServletPath()); throw new AccessException(message); } - final Claims claims = getClaims(token); + final Claims claims = getClaims(token, request); Long userId = Long.parseLong(claims.getOrDefault(TOKEN_USER_ID, 0).toString()); String userName = String.valueOf(claims.get(TOKEN_USER_NAME)); String email = String.valueOf(claims.get(TOKEN_USER_EMAIL)); @@ -87,11 +88,13 @@ public class UserTokenUtils { return UserWithPassword.get(userId, userName, displayName, email, password, isAdmin); } - private Claims getClaims(String token) { + private Claims getClaims(String token, HttpServletRequest request) { Claims claims; try { + String appKey = getAppKey(request); + String tokenSecret = getTokenSecret(appKey); claims = Jwts.parser() - .setSigningKey(authenticationConfig.getTokenSecret().getBytes(StandardCharsets.UTF_8)) + .setSigningKey(tokenSecret.getBytes(StandardCharsets.UTF_8)) .parseClaimsJws(token.startsWith(TOKEN_PREFIX) ? token.substring(token.indexOf(TOKEN_PREFIX) + TOKEN_PREFIX.length()).trim() : token.trim()).getBody(); @@ -101,14 +104,15 @@ public class UserTokenUtils { return claims; } - private String generate(Map claims) { - return toTokenString(claims); + private String generate(Map claims, String appKey) { + return toTokenString(claims, appKey); } - private String toTokenString(Map claims) { + private String toTokenString(Map claims, String appKey) { Long tokenTimeout = authenticationConfig.getTokenTimeout(); long expiration = Long.parseLong(claims.get(TOKEN_CREATE_TIME) + "") + tokenTimeout; Date expirationDate = new Date(expiration); + String tokenSecret = getTokenSecret(appKey); SignatureAlgorithm.valueOf(TOKEN_ALGORITHM); return Jwts.builder() @@ -116,8 +120,24 @@ public class UserTokenUtils { .setSubject(claims.get(TOKEN_USER_NAME).toString()) .setExpiration(expirationDate) .signWith(SignatureAlgorithm.valueOf(TOKEN_ALGORITHM), - authenticationConfig.getTokenSecret().getBytes(StandardCharsets.UTF_8)) + tokenSecret.getBytes(StandardCharsets.UTF_8)) .compact(); } + private String getTokenSecret(String appKey) { + Map appKeyToSecretMap = authenticationConfig.getAppKeyToSecretMap(); + String secret = appKeyToSecretMap.get(appKey); + if (StringUtils.isBlank(secret)) { + throw new AccessException("get secret from appKey failed :" + appKey); + } + return secret; + } + + private String getAppKey(HttpServletRequest request) { + String appKey = request.getHeader(authenticationConfig.getTokenHttpHeaderAppKey()); + if (StringUtils.isBlank(appKey)) { + appKey = authenticationConfig.getTokenDefaultAppKey(); + } + return appKey; + } } diff --git a/webapp/packages/supersonic-fe/src/pages/Login/index.tsx b/webapp/packages/supersonic-fe/src/pages/Login/index.tsx index 7e1e4f7e4..5e8b32ed1 100644 --- a/webapp/packages/supersonic-fe/src/pages/Login/index.tsx +++ b/webapp/packages/supersonic-fe/src/pages/Login/index.tsx @@ -107,7 +107,7 @@ const LoginPage: React.FC = () => { } />