fix spring cycle dependence JwtTokenManager (#8418)

* fix spring cycle dependence  JwtTokenManager

* remove unuse code

* check code style

* update test metrhod

* remove unuse code

* remove NacosAuthConfig logic from jwttoken

* fix testUpgradeCheckSucc test
This commit is contained in:
chenhao26 2022-05-23 09:53:08 +08:00 committed by GitHub
parent dbc1be8d8d
commit 74c3355b71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 79 additions and 92 deletions

View File

@ -241,6 +241,7 @@ public class UpgradeJudgement extends Subscriber<MembersChangeEvent> {
if (null != upgradeChecker) {
upgradeChecker.shutdownNow();
}
NotifyCenter.deregisterSubscriber(this);
}
/**

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.naming.core.v2.upgrade;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.core.cluster.Member;
import com.alibaba.nacos.core.cluster.MemberMetaDataConstants;
@ -96,6 +97,7 @@ public class UpgradeJudgementTest {
ApplicationUtils.injectContext(context);
upgradeJudgement = new UpgradeJudgement(raftPeerSet, raftCore, versionJudgement, memberManager, serviceManager,
upgradeStates, doubleWriteDelayTaskEngine);
NotifyCenter.deregisterSubscriber(upgradeJudgement);
}
@After

View File

@ -16,11 +16,14 @@
package com.alibaba.nacos.plugin.auth.impl;
import com.alibaba.nacos.auth.config.AuthConfigs;
import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.io.DecodingException;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
@ -28,8 +31,11 @@ import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.Properties;
/**
* JWT token manager.
@ -42,8 +48,38 @@ public class JwtTokenManager {
private static final String AUTHORITIES_KEY = "auth";
@Autowired
private NacosAuthConfig nacosAuthConfig;
private final AuthConfigs authConfigs;
/**
* secret key.
*/
private String secretKey;
/**
* secret key byte array.
*/
private byte[] secretKeyBytes;
/**
* Token validity time(seconds).
*/
private long tokenValidityInSeconds;
public JwtTokenManager(AuthConfigs authConfigs) {
this.authConfigs = authConfigs;
}
/**
* init tokenValidityInSeconds and secretKey properties.
*/
@PostConstruct
public void initProperties() {
Properties properties = authConfigs.getAuthPluginProperties(AuthConstants.AUTH_PLUGIN_TYPE);
String validitySeconds = properties
.getProperty(AuthConstants.TOKEN_EXPIRE_SECONDS, AuthConstants.DEFAULT_TOKEN_EXPIRE_SECONDS);
tokenValidityInSeconds = Long.parseLong(validitySeconds);
secretKey = properties.getProperty(AuthConstants.TOKEN_SECRET_KEY, AuthConstants.DEFAULT_TOKEN_SECRET_KEY);
}
/**
* Create token.
@ -67,11 +103,11 @@ public class JwtTokenManager {
Date validity;
validity = new Date(now + nacosAuthConfig.getTokenValidityInSeconds() * 1000L);
validity = new Date(now + this.getTokenValidityInSeconds() * 1000L);
Claims claims = Jwts.claims().setSubject(userName);
return Jwts.builder().setClaims(claims).setExpiration(validity)
.signWith(Keys.hmacShaKeyFor(nacosAuthConfig.getSecretKeyBytes()), SignatureAlgorithm.HS256).compact();
.signWith(Keys.hmacShaKeyFor(this.getSecretKeyBytes()), SignatureAlgorithm.HS256).compact();
}
/**
@ -81,7 +117,7 @@ public class JwtTokenManager {
* @return auth info
*/
public Authentication getAuthentication(String token) {
Claims claims = Jwts.parserBuilder().setSigningKey(nacosAuthConfig.getSecretKeyBytes()).build()
Claims claims = Jwts.parserBuilder().setSigningKey(this.getSecretKeyBytes()).build()
.parseClaimsJws(token).getBody();
List<GrantedAuthority> authorities = AuthorityUtils
@ -97,7 +133,22 @@ public class JwtTokenManager {
* @param token token
*/
public void validateToken(String token) {
Jwts.parserBuilder().setSigningKey(nacosAuthConfig.getSecretKeyBytes()).build().parseClaimsJws(token);
Jwts.parserBuilder().setSigningKey(this.getSecretKeyBytes()).build().parseClaimsJws(token);
}
public byte[] getSecretKeyBytes() {
if (secretKeyBytes == null) {
try {
secretKeyBytes = Decoders.BASE64.decode(secretKey);
} catch (DecodingException e) {
secretKeyBytes = secretKey.getBytes(StandardCharsets.UTF_8);
}
}
return secretKeyBytes;
}
public long getTokenValidityInSeconds() {
return tokenValidityInSeconds;
}
}

View File

@ -19,12 +19,9 @@ package com.alibaba.nacos.plugin.auth.impl;
import com.alibaba.nacos.auth.config.AuthConfigs;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.core.code.ControllerMethodsCache;
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.filter.JwtAuthenticationTokenFilter;
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.io.DecodingException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
@ -42,8 +39,6 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
import org.springframework.web.cors.CorsUtils;
import javax.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;
import java.util.Properties;
/**
* Spring security config.
@ -75,21 +70,6 @@ public class NacosAuthConfig extends WebSecurityConfigurerAdapter {
private final ControllerMethodsCache methodsCache;
/**
* secret key.
*/
private String secretKey;
/**
* secret key byte array.
*/
private byte[] secretKeyBytes;
/**
* Token validity time(seconds).
*/
private long tokenValidityInSeconds;
public NacosAuthConfig(Environment env, JwtTokenManager tokenProvider, AuthConfigs authConfigs,
NacosUserDetailsServiceImpl userDetailsService,
ObjectProvider<LdapAuthenticationProvider> ldapAuthenticationProvider,
@ -110,15 +90,6 @@ public class NacosAuthConfig extends WebSecurityConfigurerAdapter {
@PostConstruct
public void init() {
methodsCache.initClassMethod("com.alibaba.nacos.plugin.auth.impl.controller");
initProperties();
}
private void initProperties() {
Properties properties = authConfigs.getAuthPluginProperties(AuthConstants.AUTH_PLUGIN_TYPE);
String validitySeconds = properties
.getProperty(AuthConstants.TOKEN_EXPIRE_SECONDS, AuthConstants.DEFAULT_TOKEN_EXPIRE_SECONDS);
tokenValidityInSeconds = Long.parseLong(validitySeconds);
secretKey = properties.getProperty(AuthConstants.TOKEN_SECRET_KEY, AuthConstants.DEFAULT_TOKEN_SECRET_KEY);
}
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@ -177,20 +148,4 @@ public class NacosAuthConfig extends WebSecurityConfigurerAdapter {
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
public byte[] getSecretKeyBytes() {
if (secretKeyBytes == null) {
try {
secretKeyBytes = Decoders.BASE64.decode(secretKey);
} catch (DecodingException e) {
secretKeyBytes = secretKey.getBytes(StandardCharsets.UTF_8);
}
}
return secretKeyBytes;
}
public long getTokenValidityInSeconds() {
return tokenValidityInSeconds;
}
}

View File

@ -25,7 +25,6 @@ import com.alibaba.nacos.common.utils.JacksonUtils;
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.NacosAuthConfig;
import com.alibaba.nacos.plugin.auth.impl.NacosAuthManager;
import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
import com.alibaba.nacos.plugin.auth.impl.constant.AuthSystemTypes;
@ -83,9 +82,6 @@ public class UserController {
@Autowired
private AuthConfigs authConfigs;
@Autowired
private NacosAuthConfig nacosAuthConfig;
@Autowired
private NacosAuthManager authManager;
@ -218,7 +214,7 @@ public class UserController {
ObjectNode result = JacksonUtils.createEmptyJsonNode();
result.put(Constants.ACCESS_TOKEN, user.getToken());
result.put(Constants.TOKEN_TTL, nacosAuthConfig.getTokenValidityInSeconds());
result.put(Constants.TOKEN_TTL, jwtTokenManager.getTokenValidityInSeconds());
result.put(Constants.GLOBAL_ADMIN, user.isGlobalAdmin());
result.put(Constants.USERNAME, user.getUserName());
return result;

View File

@ -17,16 +17,12 @@
package com.alibaba.nacos.plugin.auth.impl;
import com.alibaba.nacos.auth.config.AuthConfigs;
import com.alibaba.nacos.core.code.ControllerMethodsCache;
import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
import io.jsonwebtoken.lang.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.beans.factory.ObjectProvider;
import java.lang.reflect.Field;
import java.util.Properties;
import static org.mockito.Mockito.when;
@ -37,18 +33,9 @@ public class JwtTokenManagerTest {
@Mock
private AuthConfigs authConfigs;
@Mock
private ControllerMethodsCache methodsCache;
@Mock
private ObjectProvider<LdapAuthenticationProvider> ldapAuthenticationProvider;
private NacosAuthConfig nacosAuthConfig;
@Test
public void testCreateTokenAndSecretKeyWithoutSpecialSymbol() throws NoSuchFieldException, IllegalAccessException {
createToken("SecretKey0123$567890$234567890123456789012345678901234567890123456789");
}
@Test
@ -61,23 +48,10 @@ public class JwtTokenManagerTest {
properties.setProperty(AuthConstants.TOKEN_SECRET_KEY, secretKey);
properties.setProperty(AuthConstants.TOKEN_EXPIRE_SECONDS, "300");
when(authConfigs.getAuthPluginProperties(AuthConstants.AUTH_PLUGIN_TYPE)).thenReturn(properties);
nacosAuthConfig = new NacosAuthConfig(null, null, authConfigs, null,
ldapAuthenticationProvider, methodsCache);
nacosAuthConfig.init();
JwtTokenManager jwtTokenManager = new JwtTokenManager();
injectProperty(jwtTokenManager, "nacosAuthConfig", nacosAuthConfig);
JwtTokenManager jwtTokenManager = new JwtTokenManager(authConfigs);
jwtTokenManager.initProperties();
String nacosToken = jwtTokenManager.createToken("nacos");
Assert.notNull(nacosToken);
jwtTokenManager.validateToken(nacosToken);
}
private void injectProperty(Object o, String propertyName, Object value)
throws NoSuchFieldException, IllegalAccessException {
Class<?> aClass = o.getClass();
Field declaredField = aClass.getDeclaredField(propertyName);
declaredField.setAccessible(true);
declaredField.set(o, value);
}
}

View File

@ -18,8 +18,9 @@ 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.NacosAuthConfig;
import com.alibaba.nacos.plugin.auth.impl.JwtTokenManager;
import com.alibaba.nacos.plugin.auth.impl.NacosAuthManager;
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.users.NacosUser;
import com.fasterxml.jackson.databind.JsonNode;
@ -32,6 +33,7 @@ import org.mockito.junit.MockitoJUnitRunner;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.util.Properties;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertThat;
@ -41,6 +43,9 @@ import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class UserControllerTest {
@Mock(lenient = true)
JwtTokenManager jwtTokenManager;
@Mock
private HttpServletRequest request;
@ -50,9 +55,6 @@ public class UserControllerTest {
@Mock
private AuthConfigs authConfigs;
@Mock
private NacosAuthConfig nacosAuthConfig;
@Mock
private NacosAuthManager authManager;
@ -69,19 +71,25 @@ public class UserControllerTest {
user.setToken("1234567890");
injectObject("authConfigs", authConfigs);
injectObject("authManager", authManager);
injectObject("nacosAuthConfig", nacosAuthConfig);
Properties properties = new Properties();
properties.setProperty(AuthConstants.TOKEN_SECRET_KEY, "SecretKey012345678901234567890123456789012345678901234567890123456789");
properties.setProperty(AuthConstants.TOKEN_EXPIRE_SECONDS, "300");
when(authConfigs.getAuthPluginProperties(AuthConstants.AUTH_PLUGIN_TYPE)).thenReturn(properties);
JwtTokenManager jwtTokenManager = new JwtTokenManager(authConfigs);
jwtTokenManager.initProperties();
injectObject("jwtTokenManager", jwtTokenManager);
}
@Test
public void testLoginWithAuthedUser() throws AccessException {
when(authManager.login(request)).thenReturn(user);
when(authConfigs.getNacosAuthSystemType()).thenReturn(AuthSystemTypes.NACOS.name());
when(nacosAuthConfig.getTokenValidityInSeconds()).thenReturn(18000L);
when(jwtTokenManager.getTokenValidityInSeconds()).thenReturn(18000L);
Object actual = userController.login("nacos", "nacos", response, request);
assertThat(actual, instanceOf(JsonNode.class));
String actualString = actual.toString();
assertTrue(actualString.contains("\"accessToken\":\"1234567890\""));
assertTrue(actualString.contains("\"tokenTtl\":18000"));
assertTrue(actualString.contains("\"tokenTtl\":300"));
assertTrue(actualString.contains("\"globalAdmin\":true"));
}