使用Spring Boot 集成Jwt令牌的时候出现了一个问题
首先报错的信息如下:
io.jsonwebtoken.MalformedJwtException: Unable to read JSON value: �z��&�r#�$�3S"
at io.jsonwebtoken.impl.DefaultJwtParser.readValue(DefaultJwtParser.java:554)
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:252)
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:481)
at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJws(DefaultJwtParser.java:541)
at com.an.server.config.security.component.JwtTokenUtil.getClaimsFromToken(JwtTokenUtil.java:132)
at com.an.server.config.security.component.JwtTokenUtil.getUsernameFromToken(JwtTokenUtil.java:51)
at com.an.server.config.WebSocketConfig$1.preSend(WebSocketConfig.java:73)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: com.fasterxml.jackson.core.JsonParseException: Illegal character ((CTRL-CHAR, code 5)): only regular white space (\r, \n, \t) is allowed between tokens
at [Source: (String)"�z��&�r#�$�3S""; line: 1, column: 2]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1851)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:707)
at com.fasterxml.jackson.core.base.ParserMinimalBase._throwInvalidSpace(ParserMinimalBase.java:685)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._skipWSOrEnd(ReaderBasedJsonParser.java:2397)
... 40 more
中间没用的代码我就直接省略了
错误原因:
我查了一下发现io.jsonwebtoken.MalformedJwtException
这个异常是来自JWT令牌校验的一个异常,说明JWT校验没有通过,一般出现这个问题可能有两种情况,
- 一种是前端在传递token的时候与后端规定的 token 格式不一样
例如:后端要求的格式是
Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImNyZWF0ZWQiOjE2NDY4OTAxOTAwNjEsImV4cCI6MTY0NzQ5NDk5MH0.lBdHE2iG6qLqYeKRTUokTh4_NJPBTWsEkJd1JMkO9zx2bWsIG9YojCJtcL-jSC3rKgkPX6m9a2tvCXNfxdZfOw
而前端传递的token
eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImNyZWF0ZWQiOjE2NDY4OTAxOTAwNjEsImV4cCI6MTY0NzQ5NDk5MH0.lBdHE2iG6qLqYeKRTUokTh4_NJPBTWsEkJd1JMkO9zx2bWsIG9YojCJtcL-jSC3rKgkPX6m9a2tvCXNfxdZfOw
这种问题建议前端进行console.log()
去看看,格式是否有问题,或者是参数名
- 另一种是后端在解析的时候没有处理好
例如:如果后端要求了 前缀 Bearer
那么就要在后端获取的时候,先去截取掉前缀
然后再进行校验
否则就会出现如上的错误
建议在调用jwtUtils进行校验之前先打印一下token,看是不是自己当初要求的格式
我是属于前后端分离开发的,那么这个问题,在最后定位发现是后端的问题,因为后端中集成websocket的时候Jwt是拎出来单独配置的,因此websocket的Jwt校验配置是独立于其他接口的,我在进行token处理的时候少写了一步
别的接口打印:
如果问题和我类似,就去找对应的jwt校验配置吧
我最后的问题是忘记截取token头 Bearer
添加如下代码:
// 判断是否为连接,如果是需要获取token,并且设置用户对象
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
// 获取前端传递的token
String token = accessor.getFirstNativeHeader("Auth-Token");
// 判断token是否存在
if (!StringUtils.isEmpty(token)) {
// 截取 token字符串 (添加如下的代码 tokenHead是自己设置好的token头)
String authToken = token.substring(tokenHead.length());
String username = jwtTokenUtil.getUsernameFromToken(authToken);
// token中存在用户名
if (!StringUtils.isEmpty(username)) {
// 登录
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// 验证token是否有效
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
accessor.setUser(authenticationToken);
}
}
}
}
最后测试通信成功
干完了 收工!!!!!