[ISSUE #9859]使用自定义的JWT生成/验证方法,而不依赖于jjwt. (#9873)

* 使用自定义jwt生成

* add unit test; fix log msg.

* add license
This commit is contained in:
云野 2023-02-02 10:47:27 +08:00 committed by GitHub
parent 986c024ccc
commit ade3f8295f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 488 additions and 72 deletions

View File

@ -29,7 +29,7 @@
<packaging>jar</packaging>
<name>nacos-plugin-default-impl ${project.version}</name>
<url>https://nacos.io</url>
<dependencies>
<dependency>
<groupId>com.alibaba.nacos</groupId>
@ -45,27 +45,13 @@
<artifactId>nacos-sys</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-config</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core</artifactId>

View File

@ -20,14 +20,12 @@ import com.alibaba.nacos.common.event.ServerConfigChangeEvent;
import com.alibaba.nacos.common.notify.Event;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.common.notify.listener.Subscriber;
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.users.NacosUser;
import com.alibaba.nacos.sys.env.EnvUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
@ -35,10 +33,7 @@ import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import javax.crypto.SecretKey;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* JWT token manager.
@ -49,6 +44,7 @@ import java.util.concurrent.TimeUnit;
@Component
public class JwtTokenManager extends Subscriber<ServerConfigChangeEvent> {
@Deprecated
private static final String AUTHORITIES_KEY = "auth";
/**
@ -56,9 +52,7 @@ public class JwtTokenManager extends Subscriber<ServerConfigChangeEvent> {
*/
private volatile long tokenValidityInSeconds;
private volatile JwtParser jwtParser;
private volatile SecretKey secretKey;
private volatile NacosJwtParser jwtParser;
public JwtTokenManager() {
NotifyCenter.registerSubscriber(this);
@ -72,14 +66,13 @@ public class JwtTokenManager extends Subscriber<ServerConfigChangeEvent> {
String encodedSecretKey = EnvUtil.getProperty(AuthConstants.TOKEN_SECRET_KEY,
AuthConstants.DEFAULT_TOKEN_SECRET_KEY);
try {
this.secretKey = Keys.hmacShaKeyFor(Decoders.BASE64.decode(encodedSecretKey));
this.jwtParser = new NacosJwtParser(encodedSecretKey);
} catch (Exception e) {
throw new IllegalArgumentException(
"the length of must great than or equal 32 bytes; And the secret key must be encoded by base64",
"the length of secret key must great than or equal 32 bytes; And the secret key must be encoded by base64",
e);
}
this.jwtParser = Jwts.parserBuilder().setSigningKey(secretKey).build();
}
/**
@ -99,13 +92,7 @@ public class JwtTokenManager extends Subscriber<ServerConfigChangeEvent> {
* @return token
*/
public String createToken(String userName) {
Date validity = new Date(
System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(this.getTokenValidityInSeconds()));
Claims claims = Jwts.claims().setSubject(userName);
return Jwts.builder().setClaims(claims).setExpiration(validity).signWith(secretKey, SignatureAlgorithm.HS256)
.compact();
return jwtParser.jwtBuilder().setUserName(userName).setExpiredTime(this.tokenValidityInSeconds).compact();
}
/**
@ -114,13 +101,12 @@ public class JwtTokenManager extends Subscriber<ServerConfigChangeEvent> {
* @param token token
* @return auth info
*/
public Authentication getAuthentication(String token) {
Claims claims = jwtParser.parseClaimsJws(token).getBody();
public Authentication getAuthentication(String token) throws AccessException {
NacosUser nacosUser = jwtParser.parse(token);
List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList(
(String) claims.get(AUTHORITIES_KEY));
List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils.EMPTY);
User principal = new User(claims.getSubject(), "", authorities);
User principal = new User(nacosUser.getUserName(), "", authorities);
return new UsernamePasswordAuthenticationToken(principal, "", authorities);
}
@ -129,8 +115,8 @@ public class JwtTokenManager extends Subscriber<ServerConfigChangeEvent> {
*
* @param token token
*/
public void validateToken(String token) {
jwtParser.parseClaimsJws(token);
public void validateToken(String token) throws AccessException {
jwtParser.parse(token);
}
public long getTokenValidityInSeconds() {

View File

@ -26,7 +26,6 @@ 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.users.NacosUser;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@ -150,16 +149,11 @@ public class NacosAuthManager {
throw new AccessException("user not found!");
}
try {
tokenManager.validateToken(token);
} catch (ExpiredJwtException e) {
throw new AccessException("token expired!");
} catch (Exception e) {
throw new AccessException("token invalid!");
}
tokenManager.validateToken(token);
}
private NacosUser getNacosUser(String token) {
private NacosUser getNacosUser(String token) throws AccessException {
Authentication authentication = tokenManager.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);

View File

@ -18,6 +18,7 @@ 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 org.springframework.security.core.Authentication;
@ -52,9 +53,12 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
String jwt = resolveToken(request);
if (StringUtils.isNotBlank(jwt) && SecurityContextHolder.getContext().getAuthentication() == null) {
this.tokenManager.validateToken(jwt);
Authentication authentication = this.tokenManager.getAuthentication(jwt);
SecurityContextHolder.getContext().setAuthentication(authentication);
try {
Authentication authentication = this.tokenManager.getAuthentication(jwt);
SecurityContextHolder.getContext().setAuthentication(authentication);
} catch (AccessException e) {
throw new RuntimeException(e);
}
}
chain.doFilter(request, response);
}

View File

@ -0,0 +1,99 @@
/*
* Copyright 1999-2022 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.jwt;
import com.alibaba.nacos.plugin.auth.exception.AccessException;
import com.alibaba.nacos.plugin.auth.impl.users.NacosUser;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Base64;
import java.util.concurrent.TimeUnit;
/**
* JwtParse.
*
* @author WeizhanYun
* @date 2023/1/15 21:38
*/
@SuppressWarnings("PMD.UndefineMagicConstantRule")
public class NacosJwtParser {
private final NacosSignatureAlgorithm signatureAlgorithm;
private final Key key;
public NacosJwtParser(String base64edKey) {
byte[] decode;
try {
decode = Base64.getDecoder().decode(base64edKey);
} catch (IllegalArgumentException e) {
decode = base64edKey.getBytes(StandardCharsets.US_ASCII);
}
int bitLength = decode.length << 3;
if (bitLength < 256) {
String msg = "The specified key byte array is " + bitLength + " bits which "
+ "is not secure enough for any JWT HMAC-SHA algorithm. The JWT "
+ "JWA Specification (RFC 7518, Section 3.2) states that keys used with HMAC-SHA algorithms MUST have a "
+ "size >= 256 bits (the key size must be greater than or equal to the hash "
+ "output size). See https://tools.ietf.org/html/rfc7518#section-3.2 for more information.";
throw new IllegalArgumentException(msg);
}
if (bitLength < 384) {
this.signatureAlgorithm = NacosSignatureAlgorithm.HS256;
} else if (bitLength < 512) {
this.signatureAlgorithm = NacosSignatureAlgorithm.HS384;
} else {
this.signatureAlgorithm = NacosSignatureAlgorithm.HS512;
}
this.key = new SecretKeySpec(decode, signatureAlgorithm.getJcaName());
}
private String sign(NacosJwtPayload payload) {
return signatureAlgorithm.sign(payload, key);
}
public JwtBuilder jwtBuilder() {
return new JwtBuilder();
}
public NacosUser parse(String token) throws AccessException {
return NacosSignatureAlgorithm.verify(token, key);
}
public class JwtBuilder {
private final NacosJwtPayload nacosJwtPayload = new NacosJwtPayload();
public JwtBuilder setUserName(String userName) {
this.nacosJwtPayload.setSub(userName);
return this;
}
public JwtBuilder setExpiredTime(long validSeconds) {
this.nacosJwtPayload.setExp(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) + validSeconds);
return this;
}
public String compact() {
return sign(nacosJwtPayload);
}
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright 1999-2022 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.jwt;
import com.alibaba.nacos.common.utils.JacksonUtils;
/**
* NacosJwtPayload.
*
* @author WeizhanYun
* @date 2023/1/15 21:27
*/
public class NacosJwtPayload {
private String sub;
private long exp = System.currentTimeMillis() / 1000L;
public String getSub() {
return sub;
}
public void setSub(String sub) {
this.sub = sub;
}
public long getExp() {
return exp;
}
public void setExp(long exp) {
this.exp = exp;
}
@Override
public String toString() {
return JacksonUtils.toJson(this);
}
}

View File

@ -0,0 +1,174 @@
/*
* Copyright 1999-2022 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.jwt;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.plugin.auth.exception.AccessException;
import com.alibaba.nacos.plugin.auth.impl.users.NacosUser;
import javax.crypto.Mac;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* SignAlgorithm.
*
* @author WeizhanYun
* @date 2023/1/15 16:42
*/
public final class NacosSignatureAlgorithm {
private static final String JWT_SEPERATOR = ".";
private static final int HEADER_POSITION = 0;
private static final int PAYLOAD_POSITION = 1;
private static final int SIGNATURE_POSITION = 2;
private static final int JWT_PARTS = 3;
private static final String HS256_JWT_HEADER = "eyJhbGciOiJIUzI1NiJ9";
private static final String HS384_JWT_HEADER = "eyJhbGciOiJIUzM4NCJ9";
private static final String HS512_JWT_HEADER = "eyJhbGciOiJIUzUxMiJ9";
private static final Base64.Encoder URL_BASE64_ENCODER = Base64.getUrlEncoder().withoutPadding();
private static final Base64.Decoder URL_BASE64_DECODER = Base64.getUrlDecoder();
private static final Map<String, NacosSignatureAlgorithm> MAP = new HashMap<>(4);
public static final NacosSignatureAlgorithm HS256 = new NacosSignatureAlgorithm("HS256", "HmacSHA256",
HS256_JWT_HEADER);
public static final NacosSignatureAlgorithm HS384 = new NacosSignatureAlgorithm("HS384", "HmacSHA384",
HS384_JWT_HEADER);
public static final NacosSignatureAlgorithm HS512 = new NacosSignatureAlgorithm("HS512", "HmacSHA512",
HS512_JWT_HEADER);
private final String algorithm;
private final String jcaName;
private final String header;
static {
MAP.put(HS256_JWT_HEADER, HS256);
MAP.put(HS384_JWT_HEADER, HS384);
MAP.put(HS512_JWT_HEADER, HS512);
}
/**
* verify jwt.
*
* @param jwt complete jwt string
* @param key for signature
* @return object for payload
* @throws AccessException access exception
*/
public static NacosUser verify(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");
}
NacosUser user = signatureAlgorithm.verify(header, payload, signature, key);
user.setToken(jwt);
return user;
}
/**
* verify jwt.
*
* @param header header of jwt
* @param payload payload of jwt
* @param signature signature of jwt
* @param key for signature
* @return object for payload
* @throws AccessException access exception
*/
public NacosUser verify(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);
if (nacosJwtPayload.getExp() >= TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())) {
return new NacosUser(nacosJwtPayload.getSub());
}
throw new AccessException("token expired!");
}
private NacosSignatureAlgorithm(String alg, String jcaName, String header) {
this.algorithm = alg;
this.jcaName = jcaName;
this.header = header;
}
String sign(NacosJwtPayload nacosJwtPayload, Key key) {
String jwtWithoutSign = header + JWT_SEPERATOR + URL_BASE64_ENCODER.encodeToString(
nacosJwtPayload.toString().getBytes(StandardCharsets.UTF_8));
Mac macInstance = getMacInstance(key);
byte[] bytes = jwtWithoutSign.getBytes(StandardCharsets.US_ASCII);
String signature = URL_BASE64_ENCODER.encodeToString(macInstance.doFinal(bytes));
return jwtWithoutSign + JWT_SEPERATOR + signature;
}
private Mac getMacInstance(Key key) {
try {
Mac instance = Mac.getInstance(jcaName);
instance.init(key);
return instance;
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
throw new IllegalArgumentException("Invalid key: " + key);
}
}
public String getAlgorithm() {
return algorithm;
}
public String getJcaName() {
return jcaName;
}
public String getHeader() {
return header;
}
}

View File

@ -17,6 +17,7 @@
package com.alibaba.nacos.plugin.auth.impl.roles;
import com.alibaba.nacos.auth.config.AuthConfigs;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.alibaba.nacos.common.utils.ConcurrentHashSet;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.config.server.model.Page;
@ -32,7 +33,6 @@ import com.alibaba.nacos.plugin.auth.impl.persistence.RoleInfo;
import com.alibaba.nacos.plugin.auth.impl.persistence.RolePersistService;
import com.alibaba.nacos.plugin.auth.impl.users.NacosUser;
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl;
import io.jsonwebtoken.lang.Collections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
@ -124,7 +124,7 @@ public class NacosRoleServiceImpl {
}
List<RoleInfo> roleInfoList = getRoles(nacosUser.getUserName());
if (Collections.isEmpty(roleInfoList)) {
if (CollectionUtils.isEmpty(roleInfoList)) {
return false;
}
@ -144,7 +144,7 @@ public class NacosRoleServiceImpl {
// For other roles, use a pattern match to decide if pass or not.
for (RoleInfo roleInfo : roleInfoList) {
List<PermissionInfo> permissionInfoList = getPermissions(roleInfo.getRole());
if (Collections.isEmpty(permissionInfoList)) {
if (CollectionUtils.isEmpty(permissionInfoList)) {
continue;
}
for (PermissionInfo permissionInfo : permissionInfoList) {
@ -165,7 +165,7 @@ public class NacosRoleServiceImpl {
Page<RoleInfo> roleInfoPage = getRolesFromDatabase(username, StringUtils.EMPTY, DEFAULT_PAGE_NO, Integer.MAX_VALUE);
if (roleInfoPage != null) {
roleInfoList = roleInfoPage.getPageItems();
if (!Collections.isEmpty(roleInfoList)) {
if (!CollectionUtils.isEmpty(roleInfoList)) {
roleInfoMap.put(username, roleInfoList);
}
}
@ -188,7 +188,7 @@ public class NacosRoleServiceImpl {
Integer.MAX_VALUE);
if (permissionInfoPage != null) {
permissionInfoList = permissionInfoPage.getPageItems();
if (!Collections.isEmpty(permissionInfoList)) {
if (!CollectionUtils.isEmpty(permissionInfoList)) {
permissionInfoMap.put(role, permissionInfoList);
}
}

View File

@ -28,6 +28,13 @@ public class NacosUser extends User {
private boolean globalAdmin = false;
public NacosUser() {
}
public NacosUser(String userName) {
setUserName(userName);
}
public String getToken() {
return token;
}

View File

@ -16,9 +16,10 @@
package com.alibaba.nacos.plugin.auth.impl;
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.sys.env.EnvUtil;
import io.jsonwebtoken.io.Encoders;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@ -28,6 +29,8 @@ import org.springframework.mock.env.MockEnvironment;
import org.springframework.security.core.Authentication;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.concurrent.TimeUnit;
@RunWith(MockitoJUnitRunner.class)
public class JwtTokenManagerTest {
@ -37,7 +40,7 @@ public class JwtTokenManagerTest {
@Before
public void setUp() {
MockEnvironment mockEnvironment = new MockEnvironment();
mockEnvironment.setProperty(AuthConstants.TOKEN_SECRET_KEY, Encoders.BASE64.encode(
mockEnvironment.setProperty(AuthConstants.TOKEN_SECRET_KEY, Base64.getEncoder().encodeToString(
"SecretKey0123$567890$234567890123456789012345678901234567890123456789".getBytes(
StandardCharsets.UTF_8)));
mockEnvironment.setProperty(AuthConstants.TOKEN_EXPIRE_SECONDS,
@ -49,19 +52,19 @@ public class JwtTokenManagerTest {
}
@Test
public void testCreateTokenAndSecretKeyWithoutSpecialSymbol() {
public void testCreateTokenAndSecretKeyWithoutSpecialSymbol() throws AccessException {
createToken("SecretKey0123567890234567890123456789012345678901234567890123456789");
}
@Test
public void testCreateTokenAndSecretKeyWithSpecialSymbol() {
public void testCreateTokenAndSecretKeyWithSpecialSymbol() throws AccessException {
createToken("SecretKey01234@#!5678901234567890123456789012345678901234567890123456789");
}
private void createToken(String secretKey) {
private void createToken(String secretKey) throws AccessException {
MockEnvironment mockEnvironment = new MockEnvironment();
mockEnvironment.setProperty(AuthConstants.TOKEN_SECRET_KEY,
Encoders.BASE64.encode(secretKey.getBytes(StandardCharsets.UTF_8)));
Base64.getEncoder().encodeToString(secretKey.getBytes(StandardCharsets.UTF_8)));
mockEnvironment.setProperty(AuthConstants.TOKEN_EXPIRE_SECONDS,
AuthConstants.DEFAULT_TOKEN_EXPIRE_SECONDS.toString());
@ -74,7 +77,7 @@ public class JwtTokenManagerTest {
}
@Test
public void getAuthentication() {
public void getAuthentication() throws AccessException {
String nacosToken = jwtTokenManager.createToken("nacos");
Authentication authentication = jwtTokenManager.getAuthentication(nacosToken);
Assert.assertNotNull(authentication);
@ -84,4 +87,34 @@ public class JwtTokenManagerTest {
public void testInvalidSecretKey() {
Assert.assertThrows(IllegalArgumentException.class, () -> createToken("0123456789ABCDEF0123456789ABCDE"));
}
@Test
public void testNacosJwtParser() throws AccessException {
String secretKey = "SecretKey0123$567890$234567890123456789012345678901234567890123456789";
MockEnvironment mockEnvironment = new MockEnvironment();
mockEnvironment.setProperty(AuthConstants.TOKEN_SECRET_KEY,
Base64.getEncoder().encodeToString(secretKey.getBytes(StandardCharsets.UTF_8)));
mockEnvironment.setProperty(AuthConstants.TOKEN_EXPIRE_SECONDS,
AuthConstants.DEFAULT_TOKEN_EXPIRE_SECONDS.toString());
EnvUtil.setEnvironment(mockEnvironment);
JwtTokenManager jwtTokenManager = new JwtTokenManager();
String nacosToken = jwtTokenManager.createToken("nacos");
Assert.assertNotNull(nacosToken);
System.out.println("oldToken: " + nacosToken);
jwtTokenManager.validateToken(nacosToken);
NacosJwtParser nacosJwtParser = new NacosJwtParser(
Base64.getEncoder().encodeToString(secretKey.getBytes(StandardCharsets.UTF_8)));
//check old token
nacosJwtParser.parse(nacosToken);
//create new token
String newToken = nacosJwtParser.jwtBuilder().setUserName("nacos").setExpiredTime(TimeUnit.DAYS.toSeconds(10L))
.compact();
System.out.println("newToken: " + newToken);
jwtTokenManager.validateToken(newToken);
}
}

View File

@ -25,7 +25,6 @@ import com.alibaba.nacos.plugin.auth.impl.constant.AuthSystemTypes;
import com.alibaba.nacos.plugin.auth.impl.users.NacosUser;
import com.alibaba.nacos.sys.env.EnvUtil;
import com.fasterxml.jackson.databind.JsonNode;
import io.jsonwebtoken.io.Encoders;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -37,6 +36,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
@ -71,7 +71,7 @@ public class UserControllerTest {
injectObject("authManager", authManager);
MockEnvironment mockEnvironment = new MockEnvironment();
mockEnvironment.setProperty(AuthConstants.TOKEN_SECRET_KEY, Encoders.BASE64.encode(
mockEnvironment.setProperty(AuthConstants.TOKEN_SECRET_KEY, Base64.getEncoder().encodeToString(
"SecretKey0123$567890$234567890123456789012345678901234567890123456789".getBytes(
StandardCharsets.UTF_8)));
mockEnvironment.setProperty(AuthConstants.TOKEN_EXPIRE_SECONDS,

View File

@ -0,0 +1,80 @@
/*
* Copyright 1999-2022 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.jwt;
import junit.framework.TestCase;
import org.junit.Test;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
/**
* NacosJwtParserTest.
*
* @author WeizhanYun
* @date 2023/2/1 16:32
*/
public class NacosJwtParserTest extends TestCase {
@Test
public void testParseWithOriginKey() {
new NacosJwtParser("SecretKey012345678901234567890123456789012345678901234567890123456789");
}
@Test
public void testParseWith16Key() {
Exception e = null;
try {
new NacosJwtParser("SecretKey0123456");
} catch (Exception exception) {
e = exception;
}
assertNotNull(e);
assertEquals(IllegalArgumentException.class, e.getClass());
}
@Test
public void testParseWith32Key() {
NacosJwtParser parser = new NacosJwtParser(encode("SecretKey01234567890123456789012"));
String token = parser.jwtBuilder().setUserName("nacos").setExpiredTime(100L).compact();
assertTrue(token.startsWith(NacosSignatureAlgorithm.HS256.getHeader()));
}
@Test
public void testParseWith48Key() {
NacosJwtParser parser = new NacosJwtParser(encode("SecretKey012345678901234567890120124568aa9012345"));
String token = parser.jwtBuilder().setUserName("nacos").setExpiredTime(100L).compact();
assertTrue(token.startsWith(NacosSignatureAlgorithm.HS384.getHeader()));
}
@Test
public void testParseWith64Key() {
NacosJwtParser parser = new NacosJwtParser(
encode("SecretKey012345678901234567SecretKey0123456789012345678901289012"));
String token = parser.jwtBuilder().setUserName("nacos").setExpiredTime(100L).compact();
assertTrue(token.startsWith(NacosSignatureAlgorithm.HS512.getHeader()));
}
private String encode(String key) {
return Base64.getEncoder().encodeToString(key.getBytes(StandardCharsets.UTF_8));
}
}