Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
非洲_平头哥
nacos
提交
ade3f829
N
nacos
项目概览
非洲_平头哥
/
nacos
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
N
nacos
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
ade3f829
编写于
2月 02, 2023
作者:
云
云野
提交者:
GitHub
2月 02, 2023
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[ISSUE #9859]使用自定义的JWT生成/验证方法,而不依赖于`jjwt`. (#9873)
* 使用自定义jwt生成 * add unit test; fix log msg. * add license
上级
986c024c
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
488 addition
and
72 deletion
+488
-72
plugin-default-impl/pom.xml
plugin-default-impl/pom.xml
+3
-17
plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/JwtTokenManager.java
...a/com/alibaba/nacos/plugin/auth/impl/JwtTokenManager.java
+15
-29
plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/NacosAuthManager.java
.../com/alibaba/nacos/plugin/auth/impl/NacosAuthManager.java
+3
-9
plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/filter/JwtAuthenticationTokenFilter.java
...plugin/auth/impl/filter/JwtAuthenticationTokenFilter.java
+7
-3
plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosJwtParser.java
...om/alibaba/nacos/plugin/auth/impl/jwt/NacosJwtParser.java
+99
-0
plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosJwtPayload.java
...m/alibaba/nacos/plugin/auth/impl/jwt/NacosJwtPayload.java
+53
-0
plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosSignatureAlgorithm.java
...a/nacos/plugin/auth/impl/jwt/NacosSignatureAlgorithm.java
+174
-0
plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/roles/NacosRoleServiceImpl.java
...ba/nacos/plugin/auth/impl/roles/NacosRoleServiceImpl.java
+5
-5
plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/users/NacosUser.java
...a/com/alibaba/nacos/plugin/auth/impl/users/NacosUser.java
+7
-0
plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/JwtTokenManagerTest.java
...m/alibaba/nacos/plugin/auth/impl/JwtTokenManagerTest.java
+40
-7
plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/controller/UserControllerTest.java
...nacos/plugin/auth/impl/controller/UserControllerTest.java
+2
-2
plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosJwtParserTest.java
...libaba/nacos/plugin/auth/impl/jwt/NacosJwtParserTest.java
+80
-0
未找到文件。
plugin-default-impl/pom.xml
浏览文件 @
ade3f829
...
...
@@ -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>
...
...
plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/JwtTokenManager.java
浏览文件 @
ade3f829
...
...
@@ -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
.
parse
ClaimsJws
(
token
);
public
void
validateToken
(
String
token
)
throws
AccessException
{
jwtParser
.
parse
(
token
);
}
public
long
getTokenValidityInSeconds
()
{
...
...
plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/NacosAuthManager.java
浏览文件 @
ade3f829
...
...
@@ -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
);
...
...
plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/filter/JwtAuthenticationTokenFilter.java
浏览文件 @
ade3f829
...
...
@@ -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
);
}
...
...
plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosJwtParser.java
0 → 100644
浏览文件 @
ade3f829
/*
* 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 Weizhan▪Yun
* @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
);
}
}
}
plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosJwtPayload.java
0 → 100644
浏览文件 @
ade3f829
/*
* 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 Weizhan▪Yun
* @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
);
}
}
plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosSignatureAlgorithm.java
0 → 100644
浏览文件 @
ade3f829
/*
* 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 Weizhan▪Yun
* @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
;
}
}
plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/roles/NacosRoleServiceImpl.java
浏览文件 @
ade3f829
...
...
@@ -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
(
Collection
Util
s
.
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
(
Collection
Util
s
.
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
(!
Collection
Util
s
.
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
(!
Collection
Util
s
.
isEmpty
(
permissionInfoList
))
{
permissionInfoMap
.
put
(
role
,
permissionInfoList
);
}
}
...
...
plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/users/NacosUser.java
浏览文件 @
ade3f829
...
...
@@ -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
;
}
...
...
plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/JwtTokenManagerTest.java
浏览文件 @
ade3f829
...
...
@@ -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
);
}
}
plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/controller/UserControllerTest.java
浏览文件 @
ade3f829
...
...
@@ -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
,
...
...
plugin-default-impl/src/test/java/com/alibaba/nacos/plugin/auth/impl/jwt/NacosJwtParserTest.java
0 → 100644
浏览文件 @
ade3f829
/*
* 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 Weizhan▪Yun
* @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
));
}
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录