Skip to content

Commit

Permalink
Merge branch 'alibaba:develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
fuhouyu authored Nov 18, 2024
2 parents d6d3fa4 + fb68b7e commit 9ef77e7
Show file tree
Hide file tree
Showing 169 changed files with 8,331 additions and 6,236 deletions.
2 changes: 2 additions & 0 deletions api/src/main/java/com/alibaba/nacos/api/common/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public class Constants {

public static final String CLIENT_VERSION_KEY = "ClientVersion";

public static final String CLIENT_IP = "ClientIp";

public static final String UNKNOWN_APP = "UnknownApp";

public static final String DEFAULT_DOMAINNAME = "commonconfig.config-host.taobao.com";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@
* @version $Id: ConfigChangeClusterSyncRequest.java, v 0.1 2020年08月11日 4:30 PM liuzunfei Exp $
*/
public class ConfigChangeClusterSyncRequest extends AbstractConfigRequest {

String tag;


long lastModified;

String grayName;

@Deprecated
boolean isBeta;

boolean isBatch;
@Deprecated
String tag;

public boolean isBeta() {
return isBeta;
Expand All @@ -42,14 +44,6 @@ public void setBeta(boolean beta) {
isBeta = beta;
}

public boolean isBatch() {
return isBatch;
}

public void setBatch(boolean batch) {
isBatch = batch;
}

/**
* Getter method for property <tt>tag</tt>.
*
Expand All @@ -68,6 +62,14 @@ public void setTag(String tag) {
this.tag = tag;
}

public String getGrayName() {
return grayName;
}

public void setGrayName(String grayName) {
this.grayName = grayName;
}

/**
* Getter method for property <tt>lastModified</tt>.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public class ConfigQueryResponse extends Response {

public static final int CONFIG_QUERY_CONFLICT = 400;

public static final int NO_RIGHT = 403;

String content;

String encryptedDataKey;
Expand Down
20 changes: 20 additions & 0 deletions api/src/main/java/com/alibaba/nacos/api/model/v2/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,26 @@ public enum ErrorCode {
*/
PARAMETER_MISMATCH(20009, "parameter mismatch"),

/**
* config gray request error.
*/
CONFIG_GRAY_OVER_MAX_VERSION_COUNT(20010, "config gray version version over max count"),

/**
* config gray tag v2 rule format invalid.
*/
CONFIG_GRAY_RULE_FORMAT_INVALID(20011, "config gray rule format invalid"),

/**
* config gray tag v2 rule version invalid.
*/
CONFIG_GRAY_VERSION_INVALID(20012, "config gray rule version invalid"),

/**
* config gray request error.
*/
CONFIG_GRAY_NAME_UNRECOGNIZED_ERROR(20013, "config gray name not recognized"),

/**
* service name error.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@

import com.alibaba.nacos.api.ability.constant.AbilityKey;
import com.alibaba.nacos.api.ability.constant.AbilityStatus;
import com.alibaba.nacos.api.common.Constants;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
* RequestMeta info.
Expand All @@ -38,6 +40,8 @@ public class RequestMeta {

private Map<String, String> labels = new HashMap<>();

private Map<String, String> appLabels = new HashMap<>();

private Map<String, Boolean> abilityTable;

public AbilityStatus getConnectionAbility(AbilityKey abilityKey) {
Expand Down Expand Up @@ -90,6 +94,35 @@ public Map<String, String> getLabels() {
*/
public void setLabels(Map<String, String> labels) {
this.labels = labels;
extractAppLabels();
}

private void extractAppLabels() {
HashMap<String, String> applabelsMap = new HashMap<String, String>(8) {
{
put(Constants.APPNAME, labels.get(Constants.APPNAME));
put(Constants.CLIENT_VERSION_KEY, clientVersion);
put(Constants.CLIENT_IP, clientIp);
}
};
labels.entrySet().stream().filter(Objects::nonNull).filter(e -> e.getKey().startsWith(Constants.APP_CONN_PREFIX)
&& e.getKey().length() > Constants.APP_CONN_PREFIX.length() && !e.getValue().trim().isEmpty())
.forEach(entry -> {
applabelsMap.putIfAbsent(entry.getKey().substring(Constants.APP_CONN_PREFIX.length()),
entry.getValue());
});
this.appLabels = applabelsMap;
}

/**
* get labels map with filter of starting with prefix #{@link Constants#APP_CONN_PREFIX} and return a new map trim
* the prefix #{@link Constants#APP_CONN_PREFIX}.
*
* @return map of labels.
* @date 2024/2/29
*/
public Map<String, String> getAppLabels() {
return appLabels;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ void before() {
configChangeClusterSyncRequest.setTag(TAG);
configChangeClusterSyncRequest.setBeta(Boolean.TRUE);
configChangeClusterSyncRequest.setLastModified(0L);
configChangeClusterSyncRequest.setBatch(false);
configChangeClusterSyncRequest.putAllHeader(HEADERS);
requestId = injectRequestUuId(configChangeClusterSyncRequest);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,5 @@ public class NacosAuthLoginConstant {

public static final String SERVER = "server";


public static final String RELOGINFLAG = "reLoginFlag";
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ public class NacosClientAuthServiceImpl extends AbstractClientAuthService {
*/
private volatile LoginIdentityContext loginIdentityContext = new LoginIdentityContext();

/**
* Re-login window in milliseconds.
*/
private final long reLoginWindow = 60000;

/**
* Login to servers.
Expand All @@ -69,9 +73,16 @@ public class NacosClientAuthServiceImpl extends AbstractClientAuthService {
@Override
public Boolean login(Properties properties) {
try {
if ((System.currentTimeMillis() - lastRefreshTime) < TimeUnit.SECONDS
.toMillis(tokenTtl - tokenRefreshWindow)) {
return true;
boolean reLoginFlag = Boolean.parseBoolean(loginIdentityContext.getParameter(NacosAuthLoginConstant.RELOGINFLAG, "false"));
if (reLoginFlag) {
if ((System.currentTimeMillis() - lastRefreshTime) < reLoginWindow) {
return true;
}
} else {
if ((System.currentTimeMillis() - lastRefreshTime) < TimeUnit.SECONDS
.toMillis(tokenTtl - tokenRefreshWindow)) {
return true;
}
}

if (StringUtils.isBlank(properties.getProperty(PropertyKeyConst.USERNAME))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1221,10 +1221,17 @@ private Response requestProxy(RpcClient rpcClientInner, Request request, long ti
throw new NacosException(NacosException.CLIENT_OVER_THRESHOLD,
"More than client-side current limit threshold");
}
Response response;
if (timeoutMills < 0) {
return rpcClientInner.request(request);
response = rpcClientInner.request(request);
} else {
response = rpcClientInner.request(request, timeoutMills);
}
// If the 403 login operation is triggered, refresh the accessToken of the client
if (response.getErrorCode() == ConfigQueryResponse.NO_RIGHT) {
reLogin();
}
return rpcClientInner.request(request, timeoutMills);
return response;
}

private RequestResource resourceBuild(Request request) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ public void start() throws NacosException {
startInternal();
}

public void reLogin() {
securityProxy.reLogin();
}

/**
* start client inner.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,8 @@ protected Map<String, String> getAppHeaders() {
result.put(APP_FILED, AppNameUtils.getAppName());
return result;
}

protected void reLogin() {
securityProxy.reLogin();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,10 @@ private <T extends Response> T requestToServer(AbstractNamingRequest request, Cl
getSecurityHeaders(request.getNamespace(), request.getGroupName(), request.getServiceName()));
response = requestTimeout < 0 ? rpcClient.request(request) : rpcClient.request(request, requestTimeout);
if (ResponseCode.SUCCESS.getCode() != response.getResultCode()) {
// If the 403 login operation is triggered, refresh the accessToken of the client
if (NacosException.NO_RIGHT == response.getErrorCode()) {
reLogin();
}
throw new NacosException(response.getErrorCode(), response.getMessage());
}
if (responseClass.isAssignableFrom(response.getClass())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,12 @@ public String callServer(String api, Map<String, String> params, Map<String, Str
if (HttpStatus.SC_NOT_MODIFIED == restResult.getCode()) {
return StringUtils.EMPTY;
}

// If the 403 login operation is triggered, refresh the accessToken of the client
if (HttpStatus.SC_FORBIDDEN == restResult.getCode()) {
reLogin();
}

throw new NacosException(restResult.getCode(), restResult.getMessage());
} catch (NacosException e) {
NAMING_LOGGER.error("[NA] failed to request", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@
package com.alibaba.nacos.client.security;

import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.auth.impl.NacosAuthLoginConstant;
import com.alibaba.nacos.plugin.auth.spi.client.ClientAuthPluginManager;
import com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;
import com.alibaba.nacos.plugin.auth.spi.client.ClientAuthService;
import com.alibaba.nacos.plugin.auth.api.RequestResource;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.lifecycle.Closeable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.List;
Expand All @@ -37,6 +40,8 @@
*/
public class SecurityProxy implements Closeable {

private static final Logger LOGGER = LoggerFactory.getLogger(SecurityProxy.class);

private ClientAuthPluginManager clientAuthPluginManager;

/**
Expand Down Expand Up @@ -85,4 +90,23 @@ public Map<String, String> getIdentityContext(RequestResource resource) {
public void shutdown() throws NacosException {
clientAuthPluginManager.shutdown();
}

/**
* Login again to refresh the accessToken.
*/
public void reLogin() {
if (clientAuthPluginManager.getAuthServiceSpiImplSet().isEmpty()) {
return;
}
for (ClientAuthService clientAuthService : clientAuthPluginManager.getAuthServiceSpiImplSet()) {
try {
LoginIdentityContext loginIdentityContext = clientAuthService.getLoginIdentityContext(new RequestResource());
if (loginIdentityContext != null) {
loginIdentityContext.setParameter(NacosAuthLoginConstant.RELOGINFLAG, "true");
}
} catch (Exception e) {
LOGGER.error("[SecurityProxy] set reLoginFlag failed.", e);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -235,4 +235,19 @@ void testGetAccessTokenWithInvalidTtl() throws Exception {
//when
assertFalse(nacosClientAuthService.login(properties));
}

@Test
void testReLogin() {
NacosClientAuthServiceImpl nacosClientAuthService = new NacosClientAuthServiceImpl();
nacosClientAuthService.login(new Properties());
// reLogin
nacosClientAuthService.getLoginIdentityContext(null).setParameter(NacosAuthLoginConstant.RELOGINFLAG, "true");
Properties properties = new Properties();
properties.setProperty(PropertyKeyConst.USERNAME, "aaa");
properties.setProperty(PropertyKeyConst.PASSWORD, "123456");
List<String> serverList = new ArrayList<>();
serverList.add("localhost");
//when
assertTrue(nacosClientAuthService.login(properties));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse;
import com.alibaba.nacos.api.config.remote.response.ConfigPublishResponse;
import com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse;
import com.alibaba.nacos.api.config.remote.response.ConfigRemoveResponse;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.config.common.GroupKey;
import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;
Expand Down Expand Up @@ -761,4 +762,21 @@ void testAddTenantListenersWithContentEnsureCacheDataSafe()
assertFalse(cacheDataFromCache2.isDiscard());
assertFalse(cacheDataFromCache2.isConsistentWithServer());
}

@Test
void testResponse403() throws NacosException {
Properties prop = new Properties();
ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());
ConfigServerListManager agent = Mockito.mock(ConfigServerListManager.class);

final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);
final ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);

ConfigRemoveResponse response = ConfigRemoveResponse.buildFailResponse("accessToken invalid");
response.setErrorCode(ConfigQueryResponse.NO_RIGHT);
Mockito.when(rpcClient.request(any(ConfigRemoveRequest.class)))
.thenReturn(response);
boolean result = clientWorker.removeConfig("a", "b", "c", "tag");
assertFalse(result);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -709,4 +709,21 @@ void testConfigAppNameLabels() throws Exception {
String appName = config.labels().get(Constants.APPNAME);
assertNotNull(appName);
}

@Test
void testResponseCode403Exception() throws NacosException {
Throwable exception = assertThrows(NacosException.class, () -> {

when(this.rpcClient.request(Mockito.any())).thenReturn(ErrorResponse.build(403, "Invalid signature"));

try {
client.registerService(SERVICE_NAME, GROUP_NAME, instance);
} catch (NacosException ex) {
assertNull(ex.getCause());

throw ex;
}
});
assertTrue(exception.getMessage().contains("Invalid signature"));
}
}
Loading

0 comments on commit 9ef77e7

Please sign in to comment.