Spring HttpServletRequest Stream关闭了IOException

时间:2018-01-19 17:28:50

标签: java spring spring-rest

我正在尝试为在移动应用上使用Facebook登录的用户生成JWT令牌。我将facebook数据发送到此功能:

COUNT(*) OVER (. . .)

我从@PostMapping("/facebook") public void registerWithFacebook(@RequestBody User user, HttpServletRequest request, HttpServletResponse response){ User loggingInUser = this.userRepository.findByUsername(user.getUsername()); if( loggingInUser == null){ user.setPassword(bCryptPasswordEncoder.encode(user.getPassword())); user.setBlocked(false); this.userRepository.save(user); } //Generate JWT token for user JWTAuthenticationFilter jwtAuthenticationFilter = new JWTAuthenticationFilter(this.authenticationManager, this.userRepository); jwtAuthenticationFilter.attemptAuthentication(request, response); } 班级致电attemptAuthentication

JWTAuthenticationFilter

public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter { private AuthenticationManager authenticationManager; private UserRepository userRepository; public JWTAuthenticationFilter() { } public JWTAuthenticationFilter(AuthenticationManager authenticationManager, UserRepository userRepository) { this.authenticationManager = authenticationManager; this.userRepository = userRepository; setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/api/login", "POST")); } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { try { User creds = new ObjectMapper() .readValue(request.getInputStream(), User.class); return authenticationManager.authenticate( new UsernamePasswordAuthenticationToken( creds.getUsername(), creds.getPassword(), new ArrayList<>()) ); } catch (IOException e) { throw new RuntimeException(e); } } @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { String token = Jwts.builder() .setSubject(((org.springframework.security.core.userdetails.User) authResult.getPrincipal()).getUsername()) .setExpiration(new Date(System.currentTimeMillis() + SecurityConstants.EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS512, SecurityConstants.JWT_SECRET.getBytes()) .compact(); response.addHeader(SecurityConstants.HEADER_STRING, token); String username = JWTAuthorizationFilter.getUsernameFromToken(token); User user = this.userRepository.findByUsername(username); Map<String, String> responseBody = new HashMap<>(); responseBody.put("token", token); responseBody.put("blocked", Boolean.toString(user.isBlocked())); responseBody.put("paid", Boolean.toString(user.isPaid())); responseBody.put("endSubscription", user.getEndSubscribtionDate() + ""); String jsonResponse = new ObjectMapper().writeValueAsString(responseBody); response.getWriter().write(jsonResponse); } } 类中的attemptAuthentication方法会引发以下错误:JWTAuthenticationFilter在以下代码行中:

java.io.IOException: Stream closed

如果我通过HTTP请求调用 User creds = new ObjectMapper() .readValue(request.getInputStream(), User.class); 方法,它可以正常工作。什么是或者可能是我得到流关闭异常的问题仅在从另一个类调用时?

谢谢!

2 个答案:

答案 0 :(得分:1)

您使用

@RequestBody User user

对于第一种情况,所以Spring框架已处理HttpServletRequest实例的输入流(默认情况下只能发生一次),解析数据并将user实例注入到处理程序中。

因此在调用handler时关闭输入流。您可以重载attemptAuthentication方法并将用户实例作为参数传递。

我认为你没有针对第二种情况的任何Spring映射,因此输入流保持“不受影响”,你可以在身份验证方法中处理它。

答案 1 :(得分:0)

我知道这个答案太迟了,但是对于将来可能会遇到此问题的人来说。

如果您完成了udalmik所说的所有操作,但仍然存在问题,请仔细检查是否已将UserDetailsS​​erviceImpl类注释为@Service。

是的,我花了四个小时才弄清楚我没有为班级添加注释。