我正在尝试为在移动应用上使用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);
方法,它可以正常工作。什么是或者可能是我得到流关闭异常的问题仅在从另一个类调用时?
谢谢!
答案 0 :(得分:1)
您使用
@RequestBody User user
对于第一种情况,所以Spring框架已处理HttpServletRequest
实例的输入流(默认情况下只能发生一次),解析数据并将user
实例注入到处理程序中。
因此在调用handler时关闭输入流。您可以重载attemptAuthentication
方法并将用户实例作为参数传递。
我认为你没有针对第二种情况的任何Spring映射,因此输入流保持“不受影响”,你可以在身份验证方法中处理它。
答案 1 :(得分:0)
我知道这个答案太迟了,但是对于将来可能会遇到此问题的人来说。
如果您完成了udalmik所说的所有操作,但仍然存在问题,请仔细检查是否已将UserDetailsServiceImpl类注释为@Service。
是的,我花了四个小时才弄清楚我没有为班级添加注释。