Add auth client: plugin and implement (#6883)

This commit is contained in:
Wuyunfan-BUPT 2021-09-14 22:55:31 -05:00 committed by GitHub
parent ac878582e4
commit b825bac845
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 734 additions and 0 deletions

View File

@ -0,0 +1,37 @@
/*
* 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.client.auth;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import java.util.List;
public abstract class AbstractClientAuthService implements ClientAuthService {
protected List<String> serverList;
protected NacosRestTemplate nacosRestTemplate;
@Override
public void setServerList(List<String> serverList) {
this.serverList = serverList;
}
@Override
public void setNacosRestTemplate(NacosRestTemplate nacosRestTemplate) {
this.nacosRestTemplate = nacosRestTemplate;
}
}

View File

@ -0,0 +1,70 @@
/*
* 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.client.auth;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.spi.NacosServiceLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* ClientAuthService classLoader.
*
* @author wuyfee
*/
public class ClientAuthPluginManager {
private static final Logger AUTHPLUGIN_LOGGER = LoggerFactory.getLogger(ClientAuthPluginManager.class);
/**
* The relationship of context type and {@link ClientAuthService}.
*/
private final Set<ClientAuthService> clientAuthServiceHashSet = new HashSet<>();
/**
* init ClientAuthService.
*/
public void init(List<String> serverList, NacosRestTemplate nacosRestTemplate) {
Collection<AbstractClientAuthService> clientAuthServices = NacosServiceLoader
.load(AbstractClientAuthService.class);
for (ClientAuthService clientAuthService : clientAuthServices) {
clientAuthService.setServerList(serverList);
clientAuthService.setNacosRestTemplate(nacosRestTemplate);
clientAuthServiceHashSet.add(clientAuthService);
}
if (clientAuthServiceHashSet.isEmpty()) {
AUTHPLUGIN_LOGGER
.warn("[ClientAuthPluginManager] Load ClientAuthService fail, No ClientAuthService implements");
}
}
/**
* get all ClientAuthService instance.
*
* @return ClientAuthService Set.
*/
public Set<ClientAuthService> getAuthServiceSpiImplSet() {
return clientAuthServiceHashSet;
}
}

View File

@ -0,0 +1,60 @@
/*
* 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.client.auth;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import java.util.List;
import java.util.Properties;
/**
* Client AuthService.
*
* @author wuyfee
*/
public interface ClientAuthService {
/**
* login(request) to service and get response.
*
* @param properties login auth information.
* @return boolean whether login success.
*/
Boolean login(Properties properties);
/**
* set login serverList.
*
* @param serverList login server list;
*/
void setServerList(List<String> serverList);
/**
* http request template.
*
* @param nacosRestTemplate nacos http request template.
*/
void setNacosRestTemplate(NacosRestTemplate nacosRestTemplate);
/**
* get login identity context.
*
* @return LoginIdentityContext this plugin loginIdentityContext.
*/
LoginIdentityContext getLoginIdentityContext();
}

View File

@ -0,0 +1,36 @@
/*
* 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.client.auth;
public class LoginAuthConstant {
public static final String ACCESSTOKEN = "accessToken";
public static final String TOKENTTL = "tokenTtl";
public static final String TOKENREFRESHWINDOW = "tokenRefreshWindow";
public static final String USERNAME = "username";
public static final String PASSWORD = "password";
public static final String COLON = ":";
public static final String SERVER = "server";
}

View File

@ -0,0 +1,54 @@
/*
* 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.client.auth;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class LoginIdentityContext {
/**
* get context from request.
*/
private final Map<String, Object> param = new HashMap<String, Object>();
/**
* get key from context.
* @param key key of request
* @return value of param key
*/
public Object getParameter(String key) {
return param.get(key); }
/**
* put key and value to param.
* @param key key of request
* @param value value of request's key
*/
public void setParameter(String key, Object value) {
param.put(key, value); }
/**
* get all keys of param map.
* @return set all param keys.
*/
public Set<String> getAllKey() {
return param.keySet();
}
}

View File

@ -0,0 +1,107 @@
/*
* 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.client.auth;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.client.auth.process.HttpLoginProcessor;
import com.alibaba.nacos.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
/**
* a ClientAuthService implement.
*
* @author wuyfee
*/
public class NacosClientAuthServiceImpl extends AbstractClientAuthService {
private static final Logger SECURITY_LOGGER = LoggerFactory.getLogger(NacosClientAuthServiceImpl.class);
/**
* TTL of token in seconds.
*/
private long tokenTtl;
/**
* Last timestamp refresh security info from server.
*/
private long lastRefreshTime;
/**
* time window to refresh security info in seconds.
*/
private long tokenRefreshWindow;
/**
* A context to take with when sending request to Nacos server.
*/
private volatile LoginIdentityContext loginIdentityContext;
/**
* Login to servers.
*
* @return true if login successfully
*/
@Override
public Boolean login(Properties properties) {
try {
if ((System.currentTimeMillis() - lastRefreshTime) < TimeUnit.SECONDS
.toMillis(tokenTtl - tokenRefreshWindow)) {
return true;
}
if (StringUtils.isBlank(properties.getProperty(PropertyKeyConst.USERNAME))) {
lastRefreshTime = System.currentTimeMillis();
return true;
}
for (String server : this.serverList) {
HttpLoginProcessor httpLoginProcessor = new HttpLoginProcessor(nacosRestTemplate);
properties.setProperty(LoginAuthConstant.SERVER, server);
LoginIdentityContext identityContext = httpLoginProcessor.getResponse(properties);
if (identityContext != null) {
if (StringUtils.isNotBlank((String) identityContext.getParameter(LoginAuthConstant.ACCESSTOKEN))) {
tokenTtl = Long.parseLong((String) identityContext.getParameter(LoginAuthConstant.TOKENTTL));
tokenRefreshWindow = tokenTtl / 10;
lastRefreshTime = System.currentTimeMillis();
loginIdentityContext = new LoginIdentityContext();
loginIdentityContext.setParameter(LoginAuthConstant.ACCESSTOKEN,
identityContext.getParameter(LoginAuthConstant.ACCESSTOKEN));
}
return true;
}
}
} catch (Throwable throwable) {
SECURITY_LOGGER.warn("[SecurityProxy] login failed, error: ", throwable);
return false;
}
return false;
}
@Override
public LoginIdentityContext getLoginIdentityContext() {
return this.loginIdentityContext;
}
}

View File

@ -0,0 +1,95 @@
/*
* 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.client.auth.process;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.client.auth.LoginAuthConstant;
import com.alibaba.nacos.client.auth.LoginIdentityContext;
import com.alibaba.nacos.client.utils.ContextPathUtil;
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.http.param.Query;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.fasterxml.jackson.databind.JsonNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import static com.alibaba.nacos.client.naming.utils.UtilAndComs.HTTP;
import static com.alibaba.nacos.client.naming.utils.UtilAndComs.webContext;
public class HttpLoginProcessor implements LoginProcessor {
private static final Logger SECURITY_LOGGER = LoggerFactory.getLogger(HttpLoginProcessor.class);
private static final String LOGIN_URL = "/v1/auth/users/login";
private final NacosRestTemplate nacosRestTemplate;
public HttpLoginProcessor(NacosRestTemplate nacosRestTemplate) {
this.nacosRestTemplate = nacosRestTemplate;
}
@Override
public LoginIdentityContext getResponse(Properties properties) {
String contextPath = ContextPathUtil
.normalizeContextPath(properties.getProperty(PropertyKeyConst.CONTEXT_PATH, webContext));
String server = properties.getProperty(LoginAuthConstant.SERVER, StringUtils.EMPTY);
String url = HTTP + server + contextPath + LOGIN_URL;
if (server.contains(Constants.HTTP_PREFIX)) {
url = server + contextPath + LOGIN_URL;
}
Map<String, String> params = new HashMap<String, String>(2);
Map<String, String> bodyMap = new HashMap<String, String>(2);
params.put(PropertyKeyConst.USERNAME, properties.getProperty(PropertyKeyConst.USERNAME, StringUtils.EMPTY));
bodyMap.put(PropertyKeyConst.PASSWORD, properties.getProperty(PropertyKeyConst.PASSWORD, StringUtils.EMPTY));
try {
HttpRestResult<String> restResult = nacosRestTemplate
.postForm(url, Header.EMPTY, Query.newInstance().initParams(params), bodyMap, String.class);
if (!restResult.ok()) {
SECURITY_LOGGER.error("login failed: {}", JacksonUtils.toJson(restResult));
return null;
}
JsonNode obj = JacksonUtils.toObj(restResult.getData());
LoginIdentityContext loginIdentityContext = new LoginIdentityContext();
if (obj.has(Constants.ACCESS_TOKEN)) {
loginIdentityContext
.setParameter(LoginAuthConstant.ACCESSTOKEN, obj.get(Constants.ACCESS_TOKEN).asText());
loginIdentityContext.setParameter(LoginAuthConstant.TOKENTTL, obj.get(Constants.TOKEN_TTL).asText());
} else {
SECURITY_LOGGER.info("[NacosClientAuthServiceImpl] ACCESS_TOKEN is empty from response");
}
return loginIdentityContext;
} catch (Exception e) {
SECURITY_LOGGER.error("[ NacosClientAuthServiceImpl] login http request failed"
+ " url: {}, params: {}, bodyMap: {}, errorMsg: {}", url, params, bodyMap, e.getMessage());
return null;
}
}
}

View File

@ -0,0 +1,31 @@
/*
* 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.client.auth.process;
import com.alibaba.nacos.client.auth.LoginIdentityContext;
import java.util.Properties;
public interface LoginProcessor {
/**
* send request to server and get result.
*
* @param properties request properties.
* @return login identity context.
*/
LoginIdentityContext getResponse(Properties properties);
}

View File

@ -0,0 +1,18 @@
#
# 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.
#
#
com.alibaba.nacos.client.auth.NacosClientAuthServiceImpl

View File

@ -0,0 +1,60 @@
/*
* 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.client.auth;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
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 java.util.List;
import java.util.Set;
/**
* {@link com.alibaba.nacos.client.auth.ClientAuthPluginManager} unit test.
*
* @author wuyfee
* @date 2021-08-12 12:56
*/
@RunWith(MockitoJUnitRunner.class)
public class ClientAuthPluginManagerTest {
private ClientAuthPluginManager clientAuthPluginManager;
@Mock
private List<String> serverlist;
@Mock
private NacosRestTemplate nacosRestTemplate;
@Before
public void setUp() throws NoSuchFieldException, IllegalAccessException {
clientAuthPluginManager = new ClientAuthPluginManager();
clientAuthPluginManager.init(serverlist, nacosRestTemplate);
}
@Test
public void testGetAuthServiceSpiImplSet() {
Set<ClientAuthService> clientAuthServiceSet = clientAuthPluginManager.getAuthServiceSpiImplSet();
Assert.assertFalse(clientAuthServiceSet.isEmpty());
}
}

View File

@ -0,0 +1,166 @@
/*
* 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.client.auth;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.http.param.Header;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class NacosClientAuthServiceImplTest {
@Test
public void testLoginSuccess() throws Exception {
//given
NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);
HttpRestResult<Object> result = new HttpRestResult<>();
result.setData("{\"accessToken\":\"ttttttttttttttttt\",\"tokenTtl\":1000}");
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
boolean ret = nacosClientAuthService.login(properties);
//then
Assert.assertTrue(ret);
}
@Test
public void testTestLoginFailCode() throws Exception {
NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);
HttpRestResult<Object> result = new HttpRestResult<>();
result.setCode(400);
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);
boolean ret = nacosClientAuthService.login(properties);
Assert.assertFalse(ret);
}
@Test
public void testTestLoginFailHttp() throws Exception {
NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);
when(nacosRestTemplate.postForm(any(), (Header) any(), any(), any(), any())).thenThrow(new Exception());
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);
boolean ret = nacosClientAuthService.login(properties);
Assert.assertFalse(ret);
}
@Test
public void testTestLoginServerListSuccess() throws Exception {
//given
NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);
HttpRestResult<Object> result = new HttpRestResult<>();
result.setData("{\"accessToken\":\"ttttttttttttttttt\",\"tokenTtl\":1000}");
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");
serverList.add("localhost");
NacosClientAuthServiceImpl nacosClientAuthService = new NacosClientAuthServiceImpl();
nacosClientAuthService.setServerList(serverList);
nacosClientAuthService.setNacosRestTemplate(nacosRestTemplate);
boolean ret = nacosClientAuthService.login(properties);
Assert.assertTrue(ret);
}
@Test
public void testTestLoginServerListLoginInWindow() throws Exception {
//given
NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);
HttpRestResult<Object> result = new HttpRestResult<>();
result.setData("{\"accessToken\":\"ttttttttttttttttt\",\"tokenTtl\":1000}");
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);
//then
boolean ret = nacosClientAuthService.login(properties);
Assert.assertTrue(ret);
}
@Test
public void testGetAccessToken() throws Exception {
NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);
HttpRestResult<Object> result = new HttpRestResult<>();
result.setData("{\"accessToken\":\"abc\",\"tokenTtl\":1000}");
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
Assert.assertTrue(nacosClientAuthService.login(properties));
//then
Assert.assertEquals("abc", nacosClientAuthService.getLoginIdentityContext().getParameter(LoginAuthConstant.ACCESSTOKEN));
}
}