我正在尝试从react应用程序登录到API,并且不断收到相同的401错误。我的Spring Boot控制台中的警告是:
2018-07-06 10:35:15.623 WARN 20328 --- [nio-8080-exec-1] c.s.s.JwtAuthorizationTokenFilter : couldn't find bearer string, will ignore the header
我的反应控制台中的错误是:
POST http://localhost:8080/api/user 401 ()
Login._this.handleSubmit @ Login.js:48
callCallback @ react-dom.development.js:100
invokeGuardedCallbackDev @ react-dom.development.js:138
invokeGuardedCallback @ react-dom.development.js:187
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js:201
executeDispatch @ react-dom.development.js:461
executeDispatchesInOrder @ react-dom.development.js:483
executeDispatchesAndRelease @ react-dom.development.js:581
executeDispatchesAndReleaseTopLevel @ react-dom.development.js:592
forEachAccumulated @ react-dom.development.js:562
runEventsInBatch @ react-dom.development.js:723
runExtractedEventsInBatch @ react-dom.development.js:732
handleTopLevel @ react-dom.development.js:4476
batchedUpdates$1 @ react-dom.development.js:16659
batchedUpdates @ react-dom.development.js:2131
dispatchEvent @ react-dom.development.js:4555
interactiveUpdates$1 @ react-dom.development.js:16714
interactiveUpdates @ react-dom.development.js:2150
dispatchInteractiveEvent @ react-dom.development.js:4532
Login.js:61 RESPONSE undefined
Login.js:48 Fetch failed loading: POST "http://localhost:8080/api/user".
我看到我没有得到回应,但不知道为什么。任何帮助,将不胜感激。谢谢!
这是我的登录组件。
class Login extends Component {
state={
username:'',
password: ''
};
handleSubmit = event => {
event.preventDefault();
return fetch(API_BASE_URL+"/user", {
method: 'POST',
headers: {
'Accept':'application/json',
'Content-Type':'application/json'},
body:JSON.stringify({
'username': this.state.username,
'password':this.state.password
})
})
.then((response) => {
response.json();
localStorage.setItem(TOKEN_KEY, response.accessToken);
console.log("RESPONSE", response.data);
})
.catch(error =>{
console.log("ERROR: ", error);
});
}
}
这是我的UserController:
public class UserController {
@Value("${jwt.header}")
private String tokenHeader;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
@Qualifier("jwtUserDetailsService")
private UserDetailsService userDetailsService;
@RequestMapping(value = "/api/user", method = RequestMethod.GET)
public JwtUser getAuthenticatedUser(HttpServletRequest request) {
String token = request.getHeader(tokenHeader).substring(7);
String username = jwtTokenUtil.getUsernameFromToken(token);
JwtUser user = (JwtUser) userDetailsService.loadUserByUsername(username);
return user;
}
}
AuthenticationRestController文件:
public class AuthenticationRestController {
@Value("${jwt.header}")
private String tokenHeader;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
PasswordEncoder passwordEncoder;
@Autowired
@Qualifier("jwtUserDetailsService")
private UserDetailsService userDetailsService;
@Autowired
private SocialJUserRepository userRepository;
@RequestMapping(value = "${jwt.route.authentication.path}", method = RequestMethod.POST)
public ResponseEntity<?> createAuthenticationToken(@RequestBody JwtAuthenticationRequest authenticationRequest) throws AuthenticationException {
authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword());
// Reload password post-security so we can generate the token
final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
final String token = jwtTokenUtil.generateToken(userDetails);
// Return the token
return ResponseEntity.ok(new JwtAuthenticationResponse(token));
}
@RequestMapping(value = "${jwt.route.authentication.refresh}", method = RequestMethod.GET)
public ResponseEntity<?> refreshAndGetAuthenticationToken(HttpServletRequest request) {
String authToken = request.getHeader(tokenHeader);
final String token = authToken.substring(7);
String username = jwtTokenUtil.getUsernameFromToken(token);
JwtUser user = (JwtUser) userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.canTokenBeRefreshed(token, user.getLastPasswordResetDate())) {
String refreshedToken = jwtTokenUtil.refreshToken(token);
return ResponseEntity.ok(new JwtAuthenticationResponse(refreshedToken));
} else {
return ResponseEntity.badRequest().body(null);
}
}
@ExceptionHandler({AuthenticationException.class})
public ResponseEntity<String> handleAuthenticationException(AuthenticationException e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(e.getMessage());
}
/**
* Authenticates the user. If something is wrong, an {@link AuthenticationException} will be thrown
*/
private void authenticate(String username, String password) {
Objects.requireNonNull(username);
Objects.requireNonNull(password);
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
} catch (DisabledException e) {
throw new AuthenticationException("User is disabled!", e);
} catch (BadCredentialsException e) {
throw new AuthenticationException("Bad credentials!", e);
}
}
@RequestMapping(value = "${jwt.route.signup.path}", method = RequestMethod.POST)
public ResponseEntity<?> registerUser(@Valid @RequestBody SignupRequest signupRequest) {
if(userRepository.existsByUsername(signupRequest.getUsername())) {
return new ResponseEntity(new ApiResponse(false, "Username is already taken!"),
HttpStatus.BAD_REQUEST);
}
if(userRepository.existsByEmail(signupRequest.getEmail())) {
return new ResponseEntity(new ApiResponse(false, "Email Address already in use!"),
HttpStatus.BAD_REQUEST);
}
// Creating user's account
socialjuser user = new socialjuser(signupRequest.getFirstname(), signupRequest.getLastname(), signupRequest.getUsername(),
signupRequest.getEmail(), signupRequest.getPassword());
user.setPassword(passwordEncoder.encode(user.getPassword()));
socialjuser result = userRepository.save(user);
URI location = ServletUriComponentsBuilder
.fromCurrentContextPath().path("/api/users/{username}")
.buildAndExpand(result.getUsername()).toUri();
return ResponseEntity.created(location).body(new ApiResponse(true, "User registered successfully"));
}
答案 0 :(得分:1)
仅在登录后才能调用getAuthenticatedUser
API。因此,Login Component中的handleSubmit
方法需要调用另一个端点,如下所示:
fetch(API_BASE_URL+"/login", {
method: 'POST', // POST or GET depending on your definition inside controller
headers: {
'Accept':'application/json',
'Content-Type':'application/json'},
body:JSON.stringify({
'username': this.state.username,
'password':this.state.password
})
})
.then((response) => {
response.json();
localStorage.setItem(TOKEN_KEY, response.accessToken); //Persist
console.log("RESPONSE", response.data);
})
.catch(error =>{
console.log("ERROR: ", error);
});
上述调用将身份验证令牌保留在本地存储中。下一步,可以通过以下方式从后端获取已登录用户的“用户详细信息”:
getUserDetails = () => {
fetch(API_BASE_URL+"/user", {
method: 'GET',
headers: {
'Authorization': `Bearer ${localStorage.getItem(TOKEN_KEY)}`,
'Accept':'application/json',
'Content-Type':'application/json'}
})
.then((response) => {
console.log("RESPONSE", response.data); // <- Your User Details here.
})
.catch(error =>{
console.log("ERROR: ", error);
});
}
当您添加带有"Bearer"
前缀的授权标头时,警告应该消失,因为它恰如其分。