diff --git a/console/src/main/resources/application.properties b/console/src/main/resources/application.properties index f777c0d25..7d7f2c315 100644 --- a/console/src/main/resources/application.properties +++ b/console/src/main/resources/application.properties @@ -125,6 +125,7 @@ nacos.core.auth.server.identity.value=security ### worked when nacos.core.auth.system.type=nacos ### The token expiration in seconds: +nacos.core.auth.plugin.nacos.token.cache.enable=false nacos.core.auth.plugin.nacos.token.expire.seconds=18000 ### The default token (Base64 string): nacos.core.auth.plugin.nacos.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789 diff --git a/distribution/conf/application.properties b/distribution/conf/application.properties index ee8ecf279..742e0512c 100644 --- a/distribution/conf/application.properties +++ b/distribution/conf/application.properties @@ -148,6 +148,7 @@ nacos.core.auth.server.identity.value=security ### worked when nacos.core.auth.system.type=nacos ### The token expiration in seconds: +nacos.core.auth.plugin.nacos.token.cache.enable=false nacos.core.auth.plugin.nacos.token.expire.seconds=18000 ### The default token (Base64 String): nacos.core.auth.plugin.nacos.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789 diff --git a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/LdapAuthConfig.java b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/LdapAuthConfig.java index 04ee8b4f3..d056b348e 100644 --- a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/LdapAuthConfig.java +++ b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/LdapAuthConfig.java @@ -21,6 +21,7 @@ import com.alibaba.nacos.plugin.auth.impl.authenticate.LdapAuthenticationManager import com.alibaba.nacos.plugin.auth.impl.configuration.ConditionOnLdapAuth; import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants; import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl; +import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate; import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @@ -83,7 +84,7 @@ public class LdapAuthConfig { @Bean @Conditional(ConditionOnLdapAuth.class) public IAuthenticationManager ldapAuthenticatoinManager(LdapTemplate ldapTemplate, - NacosUserDetailsServiceImpl userDetailsService, JwtTokenManager jwtTokenManager, + NacosUserDetailsServiceImpl userDetailsService, TokenManagerDelegate jwtTokenManager, NacosRoleServiceImpl roleService) { return new LdapAuthenticationManager(ldapTemplate, userDetailsService, jwtTokenManager, roleService, filterPrefix, caseSensitive); diff --git a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/NacosAuthConfig.java b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/NacosAuthConfig.java index fd9b40f6e..2b8819e35 100644 --- a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/NacosAuthConfig.java +++ b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/NacosAuthConfig.java @@ -26,6 +26,7 @@ import com.alibaba.nacos.plugin.auth.impl.authenticate.LdapAuthenticationManager import com.alibaba.nacos.plugin.auth.impl.constant.AuthSystemTypes; import com.alibaba.nacos.plugin.auth.impl.filter.JwtAuthenticationTokenFilter; import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl; +import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate; import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl; import org.springframework.beans.factory.ObjectProvider; import org.springframework.context.annotation.Bean; @@ -66,7 +67,7 @@ public class NacosAuthConfig extends WebSecurityConfigurerAdapter { private final Environment env; - private final JwtTokenManager tokenProvider; + private final TokenManagerDelegate tokenProvider; private final AuthConfigs authConfigs; @@ -76,7 +77,7 @@ public class NacosAuthConfig extends WebSecurityConfigurerAdapter { private final ControllerMethodsCache methodsCache; - public NacosAuthConfig(Environment env, JwtTokenManager tokenProvider, AuthConfigs authConfigs, + public NacosAuthConfig(Environment env, TokenManagerDelegate tokenProvider, AuthConfigs authConfigs, NacosUserDetailsServiceImpl userDetailsService, ObjectProvider ldapAuthenticationProvider, ControllerMethodsCache methodsCache) { @@ -166,7 +167,7 @@ public class NacosAuthConfig extends WebSecurityConfigurerAdapter { @Bean public IAuthenticationManager defaultAuthenticationManager(NacosUserDetailsServiceImpl userDetailsService, - JwtTokenManager jwtTokenManager, NacosRoleServiceImpl roleService) { + TokenManagerDelegate jwtTokenManager, NacosRoleServiceImpl roleService) { return new DefaultAuthenticationManager(userDetailsService, jwtTokenManager, roleService); } } diff --git a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/NacosAuthManager.java b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/NacosAuthManager.java index e25099b46..8ecc54114 100644 --- a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/NacosAuthManager.java +++ b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/NacosAuthManager.java @@ -25,6 +25,7 @@ import com.alibaba.nacos.plugin.auth.exception.AccessException; import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants; import com.alibaba.nacos.plugin.auth.impl.persistence.RoleInfo; import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl; +import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate; import com.alibaba.nacos.plugin.auth.impl.users.NacosUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationManager; @@ -48,7 +49,7 @@ import java.util.List; public class NacosAuthManager { @Autowired - private JwtTokenManager tokenManager; + private TokenManagerDelegate tokenManager; @Autowired private AuthenticationManager authenticationManager; diff --git a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/authenticate/AbstractAuthenticationManager.java b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/authenticate/AbstractAuthenticationManager.java index 92ffbc981..e9966982e 100644 --- a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/authenticate/AbstractAuthenticationManager.java +++ b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/authenticate/AbstractAuthenticationManager.java @@ -21,9 +21,9 @@ import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.core.utils.Loggers; import com.alibaba.nacos.plugin.auth.api.Permission; import com.alibaba.nacos.plugin.auth.exception.AccessException; -import com.alibaba.nacos.plugin.auth.impl.JwtTokenManager; import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants; import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl; +import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate; import com.alibaba.nacos.plugin.auth.impl.users.NacosUser; import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetails; import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl; @@ -41,12 +41,12 @@ public class AbstractAuthenticationManager implements IAuthenticationManager { protected NacosUserDetailsServiceImpl userDetailsService; - protected JwtTokenManager jwtTokenManager; + protected TokenManagerDelegate jwtTokenManager; protected NacosRoleServiceImpl roleService; public AbstractAuthenticationManager(NacosUserDetailsServiceImpl userDetailsService, - JwtTokenManager jwtTokenManager, NacosRoleServiceImpl roleService) { + TokenManagerDelegate jwtTokenManager, NacosRoleServiceImpl roleService) { this.userDetailsService = userDetailsService; this.jwtTokenManager = jwtTokenManager; this.roleService = roleService; diff --git a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/authenticate/DefaultAuthenticationManager.java b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/authenticate/DefaultAuthenticationManager.java index 2831e4f52..7d7a88507 100644 --- a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/authenticate/DefaultAuthenticationManager.java +++ b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/authenticate/DefaultAuthenticationManager.java @@ -16,8 +16,8 @@ package com.alibaba.nacos.plugin.auth.impl.authenticate; -import com.alibaba.nacos.plugin.auth.impl.JwtTokenManager; import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl; +import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate; import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl; /** @@ -28,8 +28,8 @@ import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl; */ public class DefaultAuthenticationManager extends AbstractAuthenticationManager { - public DefaultAuthenticationManager(NacosUserDetailsServiceImpl userDetailsService, JwtTokenManager jwtTokenManager, - NacosRoleServiceImpl roleService) { + public DefaultAuthenticationManager(NacosUserDetailsServiceImpl userDetailsService, + TokenManagerDelegate jwtTokenManager, NacosRoleServiceImpl roleService) { super(userDetailsService, jwtTokenManager, roleService); } } diff --git a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/authenticate/LdapAuthenticationManager.java b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/authenticate/LdapAuthenticationManager.java index 1dcb89777..515602861 100644 --- a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/authenticate/LdapAuthenticationManager.java +++ b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/authenticate/LdapAuthenticationManager.java @@ -19,10 +19,10 @@ package com.alibaba.nacos.plugin.auth.impl.authenticate; import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.core.utils.Loggers; import com.alibaba.nacos.plugin.auth.exception.AccessException; -import com.alibaba.nacos.plugin.auth.impl.JwtTokenManager; import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants; import com.alibaba.nacos.plugin.auth.impl.persistence.User; import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl; +import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate; import com.alibaba.nacos.plugin.auth.impl.users.NacosUser; import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetails; import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl; @@ -46,7 +46,7 @@ public class LdapAuthenticationManager extends AbstractAuthenticationManager { private final LdapTemplate ldapTemplate; public LdapAuthenticationManager(LdapTemplate ldapTemplate, NacosUserDetailsServiceImpl userDetailsService, - JwtTokenManager jwtTokenManager, NacosRoleServiceImpl roleService, String filterPrefix, + TokenManagerDelegate jwtTokenManager, NacosRoleServiceImpl roleService, String filterPrefix, boolean caseSensitive) { super(userDetailsService, jwtTokenManager, roleService); this.ldapTemplate = ldapTemplate; diff --git a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/controller/UserController.java b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/controller/UserController.java index 603dba4f9..cc8f1a07d 100644 --- a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/controller/UserController.java +++ b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/controller/UserController.java @@ -26,13 +26,13 @@ import com.alibaba.nacos.config.server.model.Page; import com.alibaba.nacos.plugin.auth.api.IdentityContext; import com.alibaba.nacos.plugin.auth.constant.ActionTypes; import com.alibaba.nacos.plugin.auth.exception.AccessException; -import com.alibaba.nacos.plugin.auth.impl.JwtTokenManager; import com.alibaba.nacos.plugin.auth.impl.authenticate.IAuthenticationManager; import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants; import com.alibaba.nacos.plugin.auth.impl.constant.AuthSystemTypes; import com.alibaba.nacos.plugin.auth.impl.persistence.RoleInfo; import com.alibaba.nacos.plugin.auth.impl.persistence.User; import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl; +import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate; import com.alibaba.nacos.plugin.auth.impl.users.NacosUser; import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl; import com.alibaba.nacos.plugin.auth.impl.utils.PasswordEncoderUtil; @@ -70,7 +70,7 @@ import java.util.List; public class UserController { @Autowired - private JwtTokenManager jwtTokenManager; + private TokenManagerDelegate jwtTokenManager; @Autowired @Deprecated @@ -232,7 +232,7 @@ public class UserController { ObjectNode result = JacksonUtils.createEmptyJsonNode(); result.put(Constants.ACCESS_TOKEN, user.getToken()); - result.put(Constants.TOKEN_TTL, jwtTokenManager.getTokenValidityInSeconds()); + result.put(Constants.TOKEN_TTL, jwtTokenManager.getTokenTtlInSeconds(user.getToken())); result.put(Constants.GLOBAL_ADMIN, iAuthenticationManager.hasGlobalAdminRole(user)); result.put(Constants.USERNAME, user.getUserName()); return result; diff --git a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/filter/JwtAuthenticationTokenFilter.java b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/filter/JwtAuthenticationTokenFilter.java index ed5b12a84..8ec6b16ef 100644 --- a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/filter/JwtAuthenticationTokenFilter.java +++ b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/filter/JwtAuthenticationTokenFilter.java @@ -19,8 +19,8 @@ package com.alibaba.nacos.plugin.auth.impl.filter; import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.plugin.auth.exception.AccessException; -import com.alibaba.nacos.plugin.auth.impl.JwtTokenManager; import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants; +import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.filter.OncePerRequestFilter; @@ -40,9 +40,9 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { private static final String TOKEN_PREFIX = "Bearer "; - private final JwtTokenManager tokenManager; + private final TokenManagerDelegate tokenManager; - public JwtAuthenticationTokenFilter(JwtTokenManager tokenManager) { + public JwtAuthenticationTokenFilter(TokenManagerDelegate tokenManager) { this.tokenManager = tokenManager; } diff --git a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosJwtParser.java b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosJwtParser.java index 203a80390..1bad56dad 100644 --- a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosJwtParser.java +++ b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosJwtParser.java @@ -78,6 +78,10 @@ public class NacosJwtParser { return NacosSignatureAlgorithm.verify(token, key); } + public long getExpireTimeInSeconds(String token) throws AccessException { + return NacosSignatureAlgorithm.getExpiredTimeInSeconds(token, key); + } + public class JwtBuilder { private final NacosJwtPayload nacosJwtPayload = new NacosJwtPayload(); diff --git a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosSignatureAlgorithm.java b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosSignatureAlgorithm.java index 952f3d6e6..335375b45 100644 --- a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosSignatureAlgorithm.java +++ b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosSignatureAlgorithm.java @@ -135,6 +135,54 @@ public final class NacosSignatureAlgorithm { throw new AccessException("token expired!"); } + /** + * get jwt expire time in seconds. + * + * @param jwt complete jwt string + * @param key for signature + * @return expire time in seconds + * @throws AccessException access exception + */ + public static long getExpiredTimeInSeconds(String jwt, Key key) throws AccessException { + if (StringUtils.isBlank(jwt)) { + throw new AccessException("user not found!"); + } + String[] split = jwt.split("\\."); + if (split.length != JWT_PARTS) { + throw new AccessException("token invalid!"); + } + String header = split[HEADER_POSITION]; + String payload = split[PAYLOAD_POSITION]; + String signature = split[SIGNATURE_POSITION]; + + NacosSignatureAlgorithm signatureAlgorithm = MAP.get(header); + if (signatureAlgorithm == null) { + throw new AccessException("unsupported signature algorithm"); + } + return signatureAlgorithm.getExpireTimeInSeconds(header, payload, signature, key); + } + + /** + * get jwt expire time in seconds. + * + * @param header header of jwt + * @param payload payload of jwt + * @param signature signature of jwt + * @param key for signature + * @return expire time in seconds + * @throws AccessException access exception + */ + public long getExpireTimeInSeconds(String header, String payload, String signature, Key key) + throws AccessException { + Mac macInstance = getMacInstance(key); + byte[] bytes = macInstance.doFinal((header + JWT_SEPERATOR + payload).getBytes(StandardCharsets.US_ASCII)); + if (!URL_BASE64_ENCODER.encodeToString(bytes).equals(signature)) { + throw new AccessException("Invalid signature"); + } + NacosJwtPayload nacosJwtPayload = JacksonUtils.toObj(URL_BASE64_DECODER.decode(payload), NacosJwtPayload.class); + return nacosJwtPayload.getExp(); + } + private NacosSignatureAlgorithm(String alg, String jcaName, String header) { this.algorithm = alg; this.jcaName = jcaName; diff --git a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/token/TokenManager.java b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/token/TokenManager.java new file mode 100644 index 000000000..45fe2450d --- /dev/null +++ b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/token/TokenManager.java @@ -0,0 +1,91 @@ +/* + * Copyright 1999-2021 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.plugin.auth.impl.token; + +import com.alibaba.nacos.plugin.auth.exception.AccessException; +import com.alibaba.nacos.plugin.auth.impl.users.NacosUser; +import org.springframework.security.core.Authentication; + +/** + * Token Manager Interface. + * + * @author majorhe + */ +public interface TokenManager { + + /** + * Create token. + * + * @param authentication auth info + * @return token + * @throws AccessException access exception + */ + String createToken(Authentication authentication) throws AccessException; + + /** + * Create token. + * + * @param userName auth info + * @return token + * @throws AccessException access exception + */ + String createToken(String userName) throws AccessException; + + /** + * Get auth Info. + * + * @param token token + * @return auth info + * @throws AccessException access exception + */ + Authentication getAuthentication(String token) throws AccessException; + + /** + * validate token. + * + * @param token token + * @throws AccessException access exception + */ + void validateToken(String token) throws AccessException; + + /** + * parse token. + * + * @param token token + * @return nacos user object + * @throws AccessException access exception + */ + NacosUser parseToken(String token) throws AccessException; + + /** + * validate token. + * + * @return token validity in seconds + * @throws AccessException access exception + */ + long getTokenValidityInSeconds() throws AccessException; + + /** + * validate token. + * + * @param token token + * @return token ttl in seconds + * @throws AccessException access exception + */ + long getTokenTtlInSeconds(String token) throws AccessException; + +} diff --git a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/token/TokenManagerDelegate.java b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/token/TokenManagerDelegate.java new file mode 100644 index 000000000..61e0adca0 --- /dev/null +++ b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/token/TokenManagerDelegate.java @@ -0,0 +1,92 @@ +/* + * Copyright 1999-2021 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.plugin.auth.impl.token; + +import com.alibaba.nacos.plugin.auth.exception.AccessException; +import com.alibaba.nacos.plugin.auth.impl.token.impl.CachedJwtTokenManager; +import com.alibaba.nacos.plugin.auth.impl.token.impl.JwtTokenManager; +import com.alibaba.nacos.plugin.auth.impl.users.NacosUser; +import com.alibaba.nacos.sys.env.EnvUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +/** + * token manager delegate. + * + * @author majorhe + */ +@Component +public class TokenManagerDelegate implements TokenManager { + + public static final String NACOS_AUTH_TOKEN_CACHING_ENABLED = "nacos.core.auth.plugin.nacos.token.cache.enable"; + + private boolean tokenCacheEnabled = false; + + @Autowired + private JwtTokenManager jwtTokenManager; + + @Autowired + private CachedJwtTokenManager cachedJwtTokenManager; + + @PostConstruct + public void init() { + tokenCacheEnabled = EnvUtil.getProperty(NACOS_AUTH_TOKEN_CACHING_ENABLED, Boolean.class, false); + } + + private TokenManager getExecuteTokenManager() { + return tokenCacheEnabled ? cachedJwtTokenManager : jwtTokenManager; + } + + @Override + public String createToken(Authentication authentication) throws AccessException { + return getExecuteTokenManager().createToken(authentication); + } + + @Override + public String createToken(String userName) throws AccessException { + return getExecuteTokenManager().createToken(userName); + } + + @Override + public Authentication getAuthentication(String token) throws AccessException { + return getExecuteTokenManager().getAuthentication(token); + } + + @Override + public void validateToken(String token) throws AccessException { + getExecuteTokenManager().validateToken(token); + } + + @Override + public NacosUser parseToken(String token) throws AccessException { + return getExecuteTokenManager().parseToken(token); + } + + @Override + public long getTokenValidityInSeconds() throws AccessException { + return getExecuteTokenManager().getTokenValidityInSeconds(); + } + + @Override + public long getTokenTtlInSeconds(String token) throws AccessException { + return getExecuteTokenManager().getTokenTtlInSeconds(token); + } + +} diff --git a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/token/impl/CachedJwtTokenManager.java b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/token/impl/CachedJwtTokenManager.java new file mode 100644 index 000000000..0f5a3f11b --- /dev/null +++ b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/token/impl/CachedJwtTokenManager.java @@ -0,0 +1,246 @@ +/* + * Copyright 1999-2021 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.plugin.auth.impl.token.impl; + +import com.alibaba.nacos.plugin.auth.exception.AccessException; +import com.alibaba.nacos.plugin.auth.impl.token.TokenManager; +import com.alibaba.nacos.plugin.auth.impl.users.NacosUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +/** + * Cached JWT token manager. + * + * @author majorhe + */ +@Component +public class CachedJwtTokenManager implements TokenManager { + + /** + * key: token string, value: token entity. + */ + private volatile Map tokenMap = new ConcurrentHashMap<>(1024); + + /** + * key: username, value: token entity. cache token created by self. + */ + private volatile Map userMap = new ConcurrentHashMap<>(128); + + @Autowired + private JwtTokenManager jwtTokenManager; + + @Scheduled(initialDelay = 30000, fixedDelay = 60000) + private void cleanExpiredToken() { + List tokens = new ArrayList<>(); + tokenMap.forEach((k, v) -> { + if (v.getExpiredTimeMills() < System.currentTimeMillis()) { + tokens.add(k); + } + }); + tokens.forEach(e -> tokenMap.remove(e)); + List users = new ArrayList<>(); + userMap.forEach((k, v) -> { + if (v.getExpiredTimeMills() < System.currentTimeMillis()) { + users.add(k); + } + }); + users.forEach(e -> userMap.remove(e)); + } + + @Override + public String createToken(Authentication authentication) throws AccessException { + return createToken(authentication.getName()); + } + + /** + * Create token. + * + * @param username auth info + * @return token + * @throws AccessException access exception + */ + public String createToken(String username) throws AccessException { + if (userMap.containsKey(username)) { + String token = userMap.get(username).getToken(); + long expiredTime = userMap.get(username).getExpiredTimeMills(); + if (!needRefresh(expiredTime)) { + return token; + } + } + String token = jwtTokenManager.createToken(username); + NacosUser user = jwtTokenManager.parseToken(token); + long expiredTime = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(getTokenValidityInSeconds()); + Authentication authentication = jwtTokenManager.getAuthentication(token); + TokenEntity model = new TokenEntity(token, username, expiredTime, authentication, user); + tokenMap.put(token, model); + userMap.put(username, model); + return token; + } + + /** + * Get auth Info. + * + * @param token token + * @return auth info + * @throws AccessException access exception + */ + public Authentication getAuthentication(String token) throws AccessException { + if (!tokenMap.containsKey(token)) { + return jwtTokenManager.getAuthentication(token); + } + return tokenMap.get(token).getAuthentication(); + } + + /** + * validate token. + * + * @param token token + * @throws AccessException access exception + */ + public void validateToken(String token) throws AccessException { + if (!tokenMap.containsKey(token)) { + // jwtTokenManager.validateToken(token) will throw runtime exception if token invalid + jwtTokenManager.validateToken(token); + // if token valid + Authentication authentication = jwtTokenManager.getAuthentication(token); + String username = authentication.getName(); + if (username == null || username.isEmpty()) { + return; + } + long expiredTime = TimeUnit.SECONDS.toMillis(jwtTokenManager.getExpiredTimeInSeconds(token)); + if (expiredTime <= System.currentTimeMillis()) { + return; + } + NacosUser user = jwtTokenManager.parseToken(token); + tokenMap.putIfAbsent(token, new TokenEntity(token, username, expiredTime, authentication, user)); + } + } + + @Override + public NacosUser parseToken(String token) throws AccessException { + if (!tokenMap.containsKey(token)) { + Authentication authentication = jwtTokenManager.getAuthentication(token); + String username = authentication.getName(); + if (username == null || username.isEmpty()) { + throw new AccessException("invalid token, username is empty"); + } + long expiredTime = TimeUnit.SECONDS.toMillis(jwtTokenManager.getExpiredTimeInSeconds(token)); + if (expiredTime <= System.currentTimeMillis()) { + throw new AccessException("expired token"); + } + NacosUser user = jwtTokenManager.parseToken(token); + tokenMap.putIfAbsent(token, new TokenEntity(token, username, expiredTime, authentication, user)); + return user; + } + return tokenMap.get(token).getNacosUser(); + } + + public long getTokenTtlInSeconds(String token) throws AccessException { + if (tokenMap.containsKey(token)) { + return TimeUnit.MILLISECONDS.toSeconds( + tokenMap.get(token).getExpiredTimeMills() - System.currentTimeMillis()); + } + return jwtTokenManager.getTokenTtlInSeconds(token); + } + + @Override + public long getTokenValidityInSeconds() { + return jwtTokenManager.getTokenValidityInSeconds(); + } + + private boolean needRefresh(long expiredTimeMills) { + long refreshWindowMills = TimeUnit.SECONDS.toMillis(getTokenValidityInSeconds() / 10); + return System.currentTimeMillis() + refreshWindowMills > expiredTimeMills; + } + + static class TokenEntity { + + private String token; + + private String userName; + + private long expiredTimeMills; + + private Authentication authentication; + + private NacosUser nacosUser; + + public TokenEntity(String token, String userName, long expiredTimeMills, Authentication authentication, + NacosUser nacosUser) { + this.token = token; + this.userName = userName; + this.expiredTimeMills = expiredTimeMills; + this.authentication = authentication; + this.nacosUser = nacosUser; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public long getExpiredTimeMills() { + return expiredTimeMills; + } + + public void setExpiredTimeMills(long expiredTimeMills) { + this.expiredTimeMills = expiredTimeMills; + } + + public Authentication getAuthentication() { + return authentication; + } + + public void setAuthentication(Authentication authentication) { + this.authentication = authentication; + } + + public NacosUser getNacosUser() { + return nacosUser; + } + + public void setNacosUser(NacosUser nacosUser) { + this.nacosUser = nacosUser; + } + + @Override + public String toString() { + return "TokenEntity{" + "token='" + token + '\'' + ", userName='" + userName + '\'' + ", expiredTimeMills=" + + expiredTimeMills + ", authentication=" + authentication + ", nacosUser=" + nacosUser + '}'; + } + } + +} diff --git a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/JwtTokenManager.java b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/token/impl/JwtTokenManager.java similarity index 89% rename from plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/JwtTokenManager.java rename to plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/token/impl/JwtTokenManager.java index 086a56571..57e772f31 100644 --- a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/JwtTokenManager.java +++ b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/token/impl/JwtTokenManager.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.alibaba.nacos.plugin.auth.impl; +package com.alibaba.nacos.plugin.auth.impl.token.impl; import com.alibaba.nacos.common.event.ServerConfigChangeEvent; import com.alibaba.nacos.common.notify.Event; @@ -24,6 +24,7 @@ import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.plugin.auth.exception.AccessException; import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants; import com.alibaba.nacos.plugin.auth.impl.jwt.NacosJwtParser; +import com.alibaba.nacos.plugin.auth.impl.token.TokenManager; import com.alibaba.nacos.plugin.auth.impl.users.NacosUser; import com.alibaba.nacos.sys.env.EnvUtil; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -34,6 +35,7 @@ import org.springframework.security.core.userdetails.User; import org.springframework.stereotype.Component; import java.util.List; +import java.util.concurrent.TimeUnit; /** * JWT token manager. @@ -42,7 +44,7 @@ import java.util.List; * @author nkorange */ @Component -public class JwtTokenManager extends Subscriber { +public class JwtTokenManager extends Subscriber implements TokenManager { @Deprecated private static final String AUTHORITIES_KEY = "auth"; @@ -129,6 +131,15 @@ public class JwtTokenManager extends Subscriber { return tokenValidityInSeconds; } + @Override + public long getTokenTtlInSeconds(String token) throws AccessException { + return jwtParser.getExpireTimeInSeconds(token) - TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()); + } + + public long getExpiredTimeInSeconds(String token) throws AccessException { + return jwtParser.getExpireTimeInSeconds(token); + } + @Override public void onEvent(ServerConfigChangeEvent event) { processProperties(); diff --git a/plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/controller/UserControllerTest.java b/plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/controller/UserControllerTest.java index 4ca1c4174..28f2388a4 100644 --- a/plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/controller/UserControllerTest.java +++ b/plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/controller/UserControllerTest.java @@ -18,10 +18,10 @@ package com.alibaba.nacos.plugin.auth.impl.controller; import com.alibaba.nacos.auth.config.AuthConfigs; import com.alibaba.nacos.plugin.auth.exception.AccessException; -import com.alibaba.nacos.plugin.auth.impl.JwtTokenManager; import com.alibaba.nacos.plugin.auth.impl.authenticate.IAuthenticationManager; import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants; import com.alibaba.nacos.plugin.auth.impl.constant.AuthSystemTypes; +import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate; import com.alibaba.nacos.plugin.auth.impl.users.NacosUser; import com.alibaba.nacos.sys.env.EnvUtil; import com.fasterxml.jackson.databind.JsonNode; @@ -39,6 +39,7 @@ import java.nio.charset.StandardCharsets; import java.util.Base64; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) @@ -56,6 +57,9 @@ public class UserControllerTest { @Mock private IAuthenticationManager authenticationManager; + @Mock + private TokenManagerDelegate tokenManagerDelegate; + private UserController userController; private NacosUser user; @@ -76,10 +80,9 @@ public class UserControllerTest { StandardCharsets.UTF_8))); mockEnvironment.setProperty(AuthConstants.TOKEN_EXPIRE_SECONDS, AuthConstants.DEFAULT_TOKEN_EXPIRE_SECONDS.toString()); - + EnvUtil.setEnvironment(mockEnvironment); - JwtTokenManager jwtTokenManager = new JwtTokenManager(); - injectObject("jwtTokenManager", jwtTokenManager); + injectObject("jwtTokenManager", tokenManagerDelegate); } @Test @@ -87,6 +90,7 @@ public class UserControllerTest { when(authenticationManager.authenticate(request)).thenReturn(user); when(authenticationManager.hasGlobalAdminRole(user)).thenReturn(true); when(authConfigs.getNacosAuthSystemType()).thenReturn(AuthSystemTypes.NACOS.name()); + when(tokenManagerDelegate.getTokenTtlInSeconds(anyString())).thenReturn(18000L); Object actual = userController.login("nacos", "nacos", response, request); assertTrue(actual instanceof JsonNode); String actualString = actual.toString(); diff --git a/plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosJwtParserTest.java b/plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosJwtParserTest.java index fa08427f1..bf772cf42 100644 --- a/plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosJwtParserTest.java +++ b/plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosJwtParserTest.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.plugin.auth.impl.jwt; +import com.alibaba.nacos.plugin.auth.exception.AccessException; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnitRunner; @@ -80,6 +81,15 @@ public class NacosJwtParserTest { assertTrue(token.startsWith(NacosSignatureAlgorithm.HS512.getHeader())); } + @Test + public void testGetExpireTimeInSeconds() throws AccessException { + NacosJwtParser parser = new NacosJwtParser( + encode("SecretKey012345678901234567SecretKey0123456789012345678901289012")); + String token = parser.jwtBuilder().setUserName("nacos").setExpiredTime(100L).compact(); + long expiredTimeSeconds = parser.getExpireTimeInSeconds(token); + assertTrue(expiredTimeSeconds * 1000 - System.currentTimeMillis() > 0); + } + private String encode(String key) { return Base64.getEncoder().encodeToString(key.getBytes(StandardCharsets.UTF_8)); } diff --git a/plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/token/TokenManagerDelegateTest.java b/plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/token/TokenManagerDelegateTest.java new file mode 100644 index 000000000..0074f9dfa --- /dev/null +++ b/plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/token/TokenManagerDelegateTest.java @@ -0,0 +1,112 @@ +/* + * Copyright 1999-2021 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.plugin.auth.impl.token; + +import com.alibaba.nacos.plugin.auth.exception.AccessException; +import com.alibaba.nacos.plugin.auth.impl.token.impl.CachedJwtTokenManager; +import com.alibaba.nacos.plugin.auth.impl.token.impl.JwtTokenManager; +import com.alibaba.nacos.plugin.auth.impl.users.NacosUser; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.security.core.Authentication; + +import java.lang.reflect.Field; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +/** + * TokenManagerDelegateTest. + * + * @author majorhe + */ +@RunWith(MockitoJUnitRunner.class) +public class TokenManagerDelegateTest { + + private TokenManagerDelegate tokenManagerDelegate; + + @Mock + private CachedJwtTokenManager cachedJwtTokenManager; + + @Mock + private JwtTokenManager jwtTokenManager; + + @Mock + private Authentication authentication; + + @Mock + private NacosUser user; + + @Before + public void setUp() throws Exception { + tokenManagerDelegate = new TokenManagerDelegate(); + injectObject("jwtTokenManager", jwtTokenManager); + injectObject("cachedJwtTokenManager", cachedJwtTokenManager); + injectObject("tokenCacheEnabled", Boolean.TRUE); + when(cachedJwtTokenManager.getTokenValidityInSeconds()).thenReturn(100L); + when(cachedJwtTokenManager.getTokenTtlInSeconds(anyString())).thenReturn(100L); + when(cachedJwtTokenManager.getAuthentication(anyString())).thenReturn(authentication); + when(cachedJwtTokenManager.parseToken(anyString())).thenReturn(user); + when(cachedJwtTokenManager.createToken(anyString())).thenReturn("token"); + when(cachedJwtTokenManager.createToken(authentication)).thenReturn("token"); + } + + @Test + public void testCreateToken1() throws AccessException { + Assert.assertEquals("token", tokenManagerDelegate.createToken(authentication)); + } + + @Test + public void testCreateToken2() throws AccessException { + Assert.assertEquals("token", tokenManagerDelegate.createToken("nacos")); + } + + @Test + public void testGetAuthentication() throws AccessException { + Assert.assertNotNull(tokenManagerDelegate.getAuthentication("token")); + } + + @Test + public void testValidateToken() throws AccessException { + tokenManagerDelegate.validateToken("token"); + } + + @Test + public void testParseToken() throws AccessException { + Assert.assertNotNull(tokenManagerDelegate.parseToken("token")); + } + + @Test + public void testGetTokenTtlInSeconds() throws AccessException { + Assert.assertTrue(tokenManagerDelegate.getTokenTtlInSeconds("token") > 0); + } + + @Test + public void testGetTokenValidityInSeconds() throws AccessException { + Assert.assertTrue(tokenManagerDelegate.getTokenValidityInSeconds() > 0); + } + + private void injectObject(String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException { + Field field = TokenManagerDelegate.class.getDeclaredField(fieldName); + field.setAccessible(true); + field.set(tokenManagerDelegate, value); + } +} diff --git a/plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/token/impl/CachedJwtTokenManagerTest.java b/plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/token/impl/CachedJwtTokenManagerTest.java new file mode 100644 index 000000000..6cf2bd30b --- /dev/null +++ b/plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/token/impl/CachedJwtTokenManagerTest.java @@ -0,0 +1,106 @@ +/* + * Copyright 1999-2021 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.plugin.auth.impl.token.impl; + +import com.alibaba.nacos.plugin.auth.exception.AccessException; +import com.alibaba.nacos.plugin.auth.impl.users.NacosUser; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.security.core.Authentication; + +import java.lang.reflect.Field; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +/** + * CachedJwtTokenManagerTest. + * + * @author Majorhe + */ +@RunWith(MockitoJUnitRunner.class) +public class CachedJwtTokenManagerTest { + + private CachedJwtTokenManager cachedJwtTokenManager; + + @Mock + private JwtTokenManager jwtTokenManager; + + @Mock + private Authentication authentication; + + @Mock + private NacosUser user; + + @Before + public void setUp() throws Exception { + cachedJwtTokenManager = new CachedJwtTokenManager(); + injectObject("jwtTokenManager", jwtTokenManager); + when(jwtTokenManager.getTokenValidityInSeconds()).thenReturn(100L); + when(jwtTokenManager.getTokenTtlInSeconds(anyString())).thenReturn(100L); + when(jwtTokenManager.getExpiredTimeInSeconds(anyString())).thenReturn(System.currentTimeMillis()); + when(jwtTokenManager.getAuthentication(anyString())).thenReturn(authentication); + when(jwtTokenManager.parseToken(anyString())).thenReturn(user); + when(jwtTokenManager.createToken(anyString())).thenReturn("token"); + when(authentication.getName()).thenReturn("nacos"); + } + + @Test + public void testCreateToken1() throws AccessException { + Assert.assertEquals("token", cachedJwtTokenManager.createToken(authentication)); + } + + @Test + public void testCreateToken2() throws AccessException { + Assert.assertEquals("token", cachedJwtTokenManager.createToken("nacos")); + } + + @Test + public void testGetAuthentication() throws AccessException { + Assert.assertNotNull(cachedJwtTokenManager.getAuthentication("token")); + } + + @Test + public void testValidateToken() throws AccessException { + cachedJwtTokenManager.validateToken("token"); + } + + @Test + public void testParseToken() throws AccessException { + Assert.assertNotNull(cachedJwtTokenManager.parseToken("token")); + } + + @Test + public void testGetTokenTtlInSeconds() throws AccessException { + Assert.assertTrue(cachedJwtTokenManager.getTokenTtlInSeconds("token") > 0); + } + + @Test + public void testGetTokenValidityInSeconds() { + Assert.assertTrue(cachedJwtTokenManager.getTokenValidityInSeconds() > 0); + } + + private void injectObject(String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException { + Field field = CachedJwtTokenManager.class.getDeclaredField(fieldName); + field.setAccessible(true); + field.set(cachedJwtTokenManager, value); + } +} diff --git a/plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/JwtTokenManagerTest.java b/plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/token/impl/JwtTokenManagerTest.java similarity index 91% rename from plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/JwtTokenManagerTest.java rename to plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/token/impl/JwtTokenManagerTest.java index 0ed279e02..f7a3a1b6a 100644 --- a/plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/JwtTokenManagerTest.java +++ b/plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/token/impl/JwtTokenManagerTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.alibaba.nacos.plugin.auth.impl; +package com.alibaba.nacos.plugin.auth.impl.token.impl; import com.alibaba.nacos.plugin.auth.exception.AccessException; import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants; @@ -88,6 +88,16 @@ public class JwtTokenManagerTest { Assert.assertThrows(IllegalArgumentException.class, () -> createToken("0123456789ABCDEF0123456789ABCDE")); } + @Test + public void testGetTokenTtlInSeconds() throws AccessException { + Assert.assertTrue(jwtTokenManager.getTokenTtlInSeconds(jwtTokenManager.createToken("nacos")) > 0); + } + + @Test + public void testGetExpiredTimeInSeconds() throws AccessException { + Assert.assertTrue(jwtTokenManager.getExpiredTimeInSeconds(jwtTokenManager.createToken("nacos")) > 0); + } + @Test public void testNacosJwtParser() throws AccessException { String secretKey = "SecretKey0123$567890$234567890123456789012345678901234567890123456789";