Spring Boot中如何在JWT存入已认证用户ID并解决解析异常
问题分析与解决方案
你遇到的JsonParseException核心原因是错误地将JWT字符串当成JSON对象来解析修改。JWT本身是Header.Payload.Signature三段式的Base64编码字符串,并非标准JSON格式,所以用ObjectMapper读取JWT字符串必然会抛出解析异常。
正确解决方案:构建JWT时直接加入userId Claim
不需要在生成JWT后再修改,而是在Jwts.builder()阶段直接添加userId的自定义Claim即可,这样生成的JWT会包含该字段,同时保证签名有效。
修正后的successfulAuthentication方法代码:
@Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { User springUser = (User) authResult.getPrincipal(); AppUser app = userRepo.findByUsername(springUser.getUsername()); Long id = app.getId(); String jwt = Jwts.builder() .setSubject(springUser.getUsername()) .setExpiration(new Date(System.currentTimeMillis() + SecurityConstants.EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS256, SecurityConstants.SECRET) .claim("roles", springUser.getAuthorities()) .claim("userId", id) // 直接在这里添加userId Claim .compact(); response.addHeader(SecurityConstants.HEADER_STRING, SecurityConstants.TOKEN_PREFIX + jwt); }
为什么原代码会报错?
原代码中你尝试用ObjectMapper.readTree(jwt)去解析JWT字符串,但JWT的结构是类似这样的:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTUyNzUyMjQxNywicm9sZXMiOlt7ImF1dGhvcml0eSI6IkFETUlOIn1dfQ.BtaWfqSy9xyDdZrEsJD6iJRVLyTpHEVGYL1NVR670Ts
整个字符串不是JSON,只有中间的Payload部分是Base64编码的JSON。直接用ObjectMapper解析整个JWT字符串,自然会触发"Unrecognized token"的解析错误。
前端Angular5获取userId的方式
在Angular中,你可以解码JWT的Payload部分来获取userId:
// 假设从请求头中获取到的token包含前缀,先移除前缀 const token = authToken.replace('Bearer ', ''); // 拆分JWT三段,取中间的Payload部分 const payload = token.split('.')[1]; // Base64解码(注意处理URL安全的Base64) const decodedPayload = JSON.parse(atob(payload.replace(/-/g, '+').replace(/_/g, '/'))); // 获取userId const userId = decodedPayload.userId;
内容的提问来源于stack exchange,提问作者dEs12ZER
相关产品推荐
相关产品推荐

