java.lang.IllegalArgumentException:密钥字节数组不能为空或为空
Posted
技术标签:
【中文标题】java.lang.IllegalArgumentException:密钥字节数组不能为空或为空【英文标题】:java.lang.IllegalArgumentException: secret key byte array cannot be null or empty 【发布时间】:2020-06-02 03:09:12 【问题描述】:我正在使用带有 JWT 的 spring-boot。
Application.properties
jwt.secret=xyz
Controller.java
@PostMapping(path = "/authenticate")
public ResponseEntity<?> createAuthenticationToken(@RequestBody JwtRequest authenticationRequest) throws Exception
authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword());
final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
final String token = jwtTokenUtil.generateToken(userDetails);
return ResponseEntity.ok(new JwtResponse(token));
JwtTokenUtil.java
@Value("$jwt.secret")
private String secret;
public String generateToken(UserDetails userDetails)
Map<String, Object> claims = new HashMap<>();
return doGenerateToken(claims, userDetails.getUsername());
private String doGenerateToken(Map<String, Object> claims, String subject)
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY*1000)).signWith(SignatureAlgorithm.HS512, secret).compact();
在jwtTokenUtil.generateToken
代码中我收到以下错误
ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException: secret key byte array cannot be null or empty.] with root cause
java.lang.IllegalArgumentException: secret key byte array cannot be null or empty.
at io.jsonwebtoken.lang.Assert.notEmpty(Assert.java:204)
at io.jsonwebtoken.impl.DefaultJwtBuilder.signWith(DefaultJwtBuilder.java:88)
at io.jsonwebtoken.impl.DefaultJwtBuilder.signWith(DefaultJwtBuilder.java:100)
at net.javaguides.springboot.helloworldapp.config.JwtTokenUtil.doGenerateToken(JwtTokenUtil.java:66)
at net.javaguides.springboot.helloworldapp.config.JwtTokenUtil.generateToken(JwtTokenUtil.java:60)
at net.javaguides.springboot.helloworldapp.controller.BasicAuthController.createAuthenticationToken(BasicAuthController.java:75)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
当我提供我的凭据时,我收到了这个错误。该应用程序已经验证了我的凭据,但在生成令牌时出现此错误。
更新:-
在调试时我看到了如下内部代码
@Override
public JwtBuilder signWith(SignatureAlgorithm alg, String base64EncodedSecretKey)
Assert.hasText(base64EncodedSecretKey, "base64-encoded secret key cannot be null or empty.");
Assert.isTrue(alg.isHmac(), "Base64-encoded key bytes may only be specified for HMAC signatures. If using RSA or Elliptic Curve, use the signWith(SignatureAlgorithm, Key) method instead.");
byte[] bytes = TextCodec.BASE64.decode(base64EncodedSecretKey);
return signWith(alg, bytes);
在这个bytes
中,我得到了空值
【问题讨论】:
异常是因为变量 'secret' 为空 @jps 错误消息很清楚,但我在 application.properties 文件中给出了jwt.secret=xyz
在您的代码中,您只需使用secret
,尚不清楚它的定义位置或方式:signWith(SignatureAlgorithm.HS512, secret)
。这是调试、设置断点并观察变量的问题。
@jps 我没有在那里给出变量声明,但在调试中我得到secret
值作为xyz
,我已经编辑了我的问题
【参考方案1】:
我认为您的密钥需要进行 base64 编码 见来源: https://github.com/jwtk/jjwt/blob/master/impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtBuilder.java#L138
尝试以下操作:
private String doGenerateToken(Map<String, Object> claims, String subject)
String encodedString = Base64.getEncoder().encodeToString(secret.getBytes())
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY*1000)).signWith(SignatureAlgorithm.HS512, encodedString ).compact();
【讨论】:
【参考方案2】:密钥太短。我有同样的错误,只是从
jwt.secret=omg
到
jwt.secret=HRlELXqpSB
解决了这个问题。
【讨论】:
【参考方案3】:我遇到了类似的问题,我的原因是代码无法获取秘密值,即使它已在应用程序属性中声明并且我正在阅读它。只需做一套秘钥,就可以生成token了。
【讨论】:
【参考方案4】:您的密钥太短。请使用长的,比如10个以上的字符。然后就好了。
【讨论】:
以上是关于java.lang.IllegalArgumentException:密钥字节数组不能为空或为空的主要内容,如果未能解决你的问题,请参考以下文章