Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ISSUE #12719] refresh the client's access token #12758

Closed
wants to merge 29 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c648249
Merge pull request #2964 from alibaba/develop
yanlinly Jun 5, 2020
5e53396
Merge pull request #3295 from alibaba/develop
KomachiSion Jul 10, 2020
a341b65
Merge pull request #3519 from alibaba/develop
KomachiSion Aug 4, 2020
c0ffb1d
Merge pull request #4119 from alibaba/develop
KomachiSion Nov 2, 2020
b9a842c
fix: 修复参数类型注释及单词拼写错误 (#4413)
xuande Dec 7, 2020
023f50c
Revert "fix: 修复参数类型注释及单词拼写错误 (#4413)" (#4417)
KomachiSion Dec 7, 2020
1d88d5d
Merge pull request #4696 from alibaba/develop
KomachiSion Jan 14, 2021
a18c27c
Merge pull request #4704 from alibaba/develop
KomachiSion Jan 14, 2021
11be620
Merge pull request #5532 from alibaba/develop
KomachiSion Apr 29, 2021
1fac5c8
Merge pull request #6052 from alibaba/develop
KomachiSion Jun 11, 2021
5a4d433
Merge pull request #6494 from alibaba/develop
KomachiSion Jul 28, 2021
8e9f718
Merge pull request #7657 from alibaba/develop
KomachiSion Jan 18, 2022
b584531
Merge pull request #8279 from alibaba/develop
KomachiSion Apr 29, 2022
41859be
Merge pull request #8902 from alibaba/develop
KomachiSion Aug 8, 2022
2eb7f73
Merge pull request #9335 from alibaba/develop
KomachiSion Oct 17, 2022
38faeea
Merge pull request #9707 from alibaba/develop
KomachiSion Dec 14, 2022
cb0422e
Merge pull request #10126 from alibaba/develop
KomachiSion Mar 17, 2023
ca6d151
Merge pull request #11266 from alibaba/develop
KomachiSion Oct 19, 2023
8ac6c84
Merge pull request #11452 from alibaba/develop
KomachiSion Nov 30, 2023
2f49431
Merge pull request #11919 from alibaba/develop
KomachiSion Apr 3, 2024
974edfe
Merge pull request #12385 from alibaba/develop
KomachiSion Jul 19, 2024
75e5de6
Merge pull request #12612 from alibaba/develop
KomachiSion Sep 5, 2024
f00cfec
Merge pull request #12723 from alibaba/develop
KomachiSion Oct 12, 2024
113cfa1
[ISSUE #12719] refresh the client's access token
lucky8987 Oct 17, 2024
e86ce7d
[ISSUE #12719] refresh the client's access token
lucky8987 Oct 17, 2024
0f242e6
Merge branch 'develop' into develop-issue#12719
lucky8987 Oct 17, 2024
1da00d4
Merge branch 'develop-issue#12719' of https://github.com/lucky8987/na…
lucky8987 Oct 17, 2024
211d9b6
[ISSUE #12719] refresh the client's access token
lucky8987 Oct 17, 2024
5cff092
[ISSUE #12719] refresh the client's access token
lucky8987 Oct 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public class NacosAuthLoginConstant {
public static final String COLON = ":";

public static final String SERVER = "server";



public static final int RELOGIN_CODE = 403;

public static final String NEXTREFRESHTIME = "nextRefreshTime";
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.auth.impl.process.HttpLoginProcessor;
import com.alibaba.nacos.common.utils.NumberUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;
import com.alibaba.nacos.plugin.auth.api.RequestResource;
Expand Down Expand Up @@ -58,8 +59,8 @@ public class NacosClientAuthServiceImpl extends AbstractClientAuthService {
* A context to take with when sending request to Nacos server.
*/
private volatile LoginIdentityContext loginIdentityContext = new LoginIdentityContext();


/**
* Login to servers.
*
Expand All @@ -69,16 +70,19 @@ public class NacosClientAuthServiceImpl extends AbstractClientAuthService {
@Override
public Boolean login(Properties properties) {
try {
if ((System.currentTimeMillis() - lastRefreshTime) < TimeUnit.SECONDS
.toMillis(tokenTtl - tokenRefreshWindow)) {

String nextRefreshTimeStr = loginIdentityContext.getParameter(NacosAuthLoginConstant.NEXTREFRESHTIME);
long nextRefreshTime = NumberUtils.toLong(nextRefreshTimeStr, 0);

if (System.currentTimeMillis() < nextRefreshTime) {
return true;
}

if (StringUtils.isBlank(properties.getProperty(PropertyKeyConst.USERNAME))) {
lastRefreshTime = System.currentTimeMillis();
loginIdentityContext.setParameter(NacosAuthLoginConstant.NEXTREFRESHTIME, "0");
return true;
}

for (String server : this.serverList) {
HttpLoginProcessor httpLoginProcessor = new HttpLoginProcessor(nacosRestTemplate);
properties.setProperty(NacosAuthLoginConstant.SERVER, server);
Expand All @@ -87,11 +91,11 @@ public Boolean login(Properties properties) {
if (identityContext.getAllKey().contains(NacosAuthLoginConstant.ACCESSTOKEN)) {
tokenTtl = Long.parseLong(identityContext.getParameter(NacosAuthLoginConstant.TOKENTTL));
tokenRefreshWindow = tokenTtl / 10;
lastRefreshTime = System.currentTimeMillis();

nextRefreshTime = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(tokenTtl - tokenRefreshWindow);
LoginIdentityContext newCtx = new LoginIdentityContext();
newCtx.setParameter(NacosAuthLoginConstant.ACCESSTOKEN,
identityContext.getParameter(NacosAuthLoginConstant.ACCESSTOKEN));
newCtx.setParameter(NacosAuthLoginConstant.NEXTREFRESHTIME, String.valueOf(nextRefreshTime));
this.loginIdentityContext = newCtx;
}
return true;
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 @@ -43,6 +43,7 @@
import com.alibaba.nacos.api.remote.response.ResponseCode;
import com.alibaba.nacos.api.selector.AbstractSelector;
import com.alibaba.nacos.api.selector.SelectorType;
import com.alibaba.nacos.client.auth.impl.NacosAuthLoginConstant;
import com.alibaba.nacos.client.env.NacosClientProperties;
import com.alibaba.nacos.client.monitor.MetricsMonitor;
import com.alibaba.nacos.client.naming.cache.ServiceInfoHolder;
Expand Down Expand Up @@ -96,6 +97,7 @@ public class NamingGrpcClientProxy extends AbstractNamingClientProxy {
public NamingGrpcClientProxy(String namespaceId, SecurityProxy securityProxy, ServerListFactory serverListFactory,
NacosClientProperties properties, ServiceInfoHolder serviceInfoHolder) throws NacosException {
super(securityProxy);
securityProxy.login(properties.asProperties());
this.namespaceId = namespaceId;
this.uuid = UUID.randomUUID().toString();
this.requestTimeout = Long.parseLong(properties.getProperty(CommonParams.NAMING_REQUEST_TIMEOUT, "-1"));
Expand Down Expand Up @@ -446,6 +448,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 (NacosAuthLoginConstant.RELOGIN_CODE == 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 @@ -28,6 +28,7 @@
import com.alibaba.nacos.api.selector.AbstractSelector;
import com.alibaba.nacos.api.selector.ExpressionSelector;
import com.alibaba.nacos.api.selector.SelectorType;
import com.alibaba.nacos.client.auth.impl.NacosAuthLoginConstant;
import com.alibaba.nacos.client.address.ServerListChangeEvent;
import com.alibaba.nacos.client.env.NacosClientProperties;
import com.alibaba.nacos.client.monitor.MetricsMonitor;
Expand Down Expand Up @@ -73,7 +74,7 @@ public class NamingHttpClientProxy extends AbstractNamingClientProxy {
private static final int DEFAULT_SERVER_PORT = 8848;

private static final String MODULE_NAME = "Naming";

private static final String IP_PARAM = "ip";

private static final String PORT_PARAM = "port";
Expand Down Expand Up @@ -440,6 +441,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 (NacosAuthLoginConstant.RELOGIN_CODE == 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,6 +17,7 @@
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;
Expand All @@ -38,6 +39,8 @@
public class SecurityProxy implements Closeable {

private ClientAuthPluginManager clientAuthPluginManager;

private Properties properties;

/**
* Construct from serverList, nacosRestTemplate, init client auth plugin.
Expand All @@ -57,6 +60,7 @@ public SecurityProxy(List<String> serverList, NacosRestTemplate nacosRestTemplat
* @param properties login identity information.
*/
public void login(Properties properties) {
this.properties = properties;
if (clientAuthPluginManager.getAuthServiceSpiImplSet().isEmpty()) {
return;
}
Expand Down Expand Up @@ -85,4 +89,19 @@ 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()) {
LoginIdentityContext loginIdentityContext = clientAuthService.getLoginIdentityContext(null);
if (loginIdentityContext != null) {
loginIdentityContext.setParameter(NacosAuthLoginConstant.NEXTREFRESHTIME, "0");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.utils.NumberUtils;
import com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
Expand Down Expand Up @@ -235,4 +237,28 @@ void testGetAccessTokenWithInvalidTtl() throws Exception {
//when
assertFalse(nacosClientAuthService.login(properties));
}

@Test
void testNextRefreshTime() throws Exception {
NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);
HttpRestResult<Object> result = new HttpRestResult<>();
result.setData("{\"accessToken\":\"abc\",\"tokenTtl\":\"60\"}");
result.setCode(200);
when(nacosRestTemplate.postForm(any(), (Header) any(), any(), any(), any())).thenReturn(result);
Properties properties = new Properties();
properties.setProperty(PropertyKeyConst.USERNAME, "aaa");
properties.setProperty(PropertyKeyConst.PASSWORD, "123456");

List<String> serverList = new ArrayList<>();
serverList.add("localhost");

NacosClientAuthServiceImpl nacosClientAuthService = new NacosClientAuthServiceImpl();
nacosClientAuthService.setServerList(serverList);
nacosClientAuthService.setNacosRestTemplate(nacosRestTemplate);
//when
nacosClientAuthService.login(properties);
LoginIdentityContext loginIdentityContext = nacosClientAuthService.getLoginIdentityContext(null);
String nextRefreshTime = loginIdentityContext.getParameter(NacosAuthLoginConstant.NEXTREFRESHTIME);
assertTrue(System.currentTimeMillis() < NumberUtils.toLong(nextRefreshTime, 0));
}
}
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"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -645,4 +645,29 @@ void testRegApiForDomain() throws NacosException {
});

}

@Test
void testCallServerFail403() throws Exception {
//given
NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);

when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenAnswer(invocationOnMock -> {
//return url
HttpRestResult<Object> res = new HttpRestResult<Object>();
res.setMessage("Invalid signature");
res.setCode(403);
return res;
});

final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField("nacosRestTemplate");
nacosRestTemplateField.setAccessible(true);
nacosRestTemplateField.set(clientProxy, nacosRestTemplate);
String api = "/api";
Map<String, String> params = new HashMap<>();
Map<String, String> body = new HashMap<>();
String method = HttpMethod.GET;
String curServer = "127.0.0.1";
//then
assertThrows(NacosException.class, () -> clientProxy.callServer(api, params, body, curServer, method));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@

import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.client.auth.impl.NacosAuthLoginConstant;
import com.alibaba.nacos.client.auth.impl.NacosClientAuthServiceImpl;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;
import com.alibaba.nacos.plugin.auth.api.RequestResource;
import com.alibaba.nacos.plugin.auth.spi.client.ClientAuthPluginManager;
import org.junit.jupiter.api.BeforeEach;
Expand Down Expand Up @@ -100,4 +102,18 @@ void testLoginWithoutAnyPlugin() throws NoSuchFieldException, IllegalAccessExcep
Map<String, String> header = securityProxy.getIdentityContext(new RequestResource());
assertTrue(header.isEmpty());
}

@Test
void testReLogin() throws NoSuchFieldException, IllegalAccessException {
NacosClientAuthServiceImpl authService = new NacosClientAuthServiceImpl();
ClientAuthPluginManager clientAuthPluginManager = mock(ClientAuthPluginManager.class);
Field clientAuthPluginManagerField = SecurityProxy.class.getDeclaredField("clientAuthPluginManager");
clientAuthPluginManagerField.setAccessible(true);
clientAuthPluginManagerField.set(securityProxy, clientAuthPluginManager);
when(clientAuthPluginManager.getAuthServiceSpiImplSet()).thenReturn(Collections.singleton(authService));
securityProxy.reLogin();
LoginIdentityContext loginIdentityContext = authService.getLoginIdentityContext(null);
String nextRefreshTime = loginIdentityContext.getParameter(NacosAuthLoginConstant.NEXTREFRESHTIME);
assertEquals(nextRefreshTime, "0");
}
}
Loading