Axios POST请求返回401错误,但在Postman上工作,(Springboot + Springboot Security)

zqdjd7g9  于 2023-06-29  发布在  iOS
关注(0)|答案(1)|浏览(236)

我正在用Springboot和Springboot Security构建一个API,以及一个与此API交互的前端。我已经测试了Postman中工作正常的所有端点,但是当使用Axios向API发送POST请求时(在我的情况下,用于生成JWT的登录请求),我收到了一个401错误,这很奇怪,因为这个请求不需要任何授权。
当尝试解决这个问题时,大多数帖子只是错误地将Auth令牌传递到请求中的问题,但这里的情况并非如此,因为端点不需要auth令牌(请参阅成功的 Postman 请求)。我发现其他类似的帖子指出这可能是一个与cors相关的问题,但是在调整控制器以包含相关的@CrossOrigin注解,并在从filterChain中排除.cors()时测试结果后,这个问题仍然存在,我几乎没有利用它来进行故障排除。

SecurityFilterChain

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {
    @Autowired
    private AuthEntryPointJwt authorizationHandler;
    @Autowired
    UserDetailsServiceImpl userDetailsService;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable().exceptionHandling().authenticationEntryPoint(authorizationHandler).and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()
                .antMatchers("/api/v1/auth/**").permitAll()
                .antMatchers("/api/v1/reviews/**").permitAll()
                .antMatchers("/api/v1/test/**").permitAll().anyRequest().authenticated();

        http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }

    @Bean
    public AuthTokenFilter authenticationJwtTokenFilter() { return new AuthTokenFilter(); }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }
}

控制器

@CrossOrigin(origins = "http://localhost:5173", maxAge = 3600)
@RestController
@RequestMapping("/api/v1/auth")
public class AuthController {
    @Autowired
    AuthenticationManager authenticationManager;
    @Autowired
    UserRepository userRepository;
    @Autowired
    PasswordEncoder encoder;
    @Autowired
    JwtUtils jwtUtils;

    @PostMapping("/signin")
    public ResponseEntity<?> authenticateUser(@RequestBody LoginRequest loginRequest) {

        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())
        );

        SecurityContextHolder.getContext().setAuthentication(authentication);
        String jwt = jwtUtils.generateJwtToken(authentication);
        UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();

        return ResponseEntity.ok(new JwtResponse(jwt, userDetails.getId(), userDetails.getUsername(), userDetails.getEmail()));
    }

auth.service.js

import axios from "axios";

const API_URL = "http://localhost:8080/api/v1/auth/";

export default class AuthService {
  login(username, password) {
    console.log(API_URL + "signin");
    console.log(username, password);
    return axios
      .post(API_URL + "signin", { username, password })
      .then((response) => {
        if (response.data.accessToken) {
          localStorage.setItem("user", JSON.stringify(response.data));
        }

        return response.data;
      });
  }

  logout() {
    localStorage.removeItem("user");
  }

  register(username, email, password) {
    return axios.post(API_URL + "signup", {
      username,
      email,
      password,
    });
  }
}

Postman请求成功

Successful Postman Request

Axios请求失败

Unsuccessful Axios Request

请求头(来自网络页签)

// GENERAL
Request URL: http://localhost:8080/api/v1/auth/signin
Request Method: POST
Status Code: 401
Remote Address: [::1]:8080
Referrer Policy: strict-origin-when-cross-origin

// RESPONSE HEADERS
HTTP/1.1 401
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: http://localhost:5173
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 0
Date: Tue, 27 Jun 2023 20:38:38 GMT
Keep-Alive: timeout=60
Connection: keep-alive

// REQUEST HEADERS
POST /api/v1/auth/signin HTTP/1.1
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Connection: keep-alive
Content-Length: 49
Content-Type: application/json
Host: localhost:8080
Origin: http://localhost:5173
Referer: http://localhost:5173/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36
sec-ch-ua: "Not.A/Brand";v="8", "Chromium";v="114", "Google Chrome";v="114"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"

我已经尝试包括尽可能多的信息,但如果有什么我可以提供,我错过了,这将有助于解决问题,让我知道。

7gyucuyw

7gyucuyw1#

您应该在POST请求的主体中传递JSON对象:

return axios
  .post(API_URL + "signin", {"username":username,"password":password })
  .then((response) => {
    if (response.data.accessToken) {
      localStorage.setItem("user", JSON.stringify(response.data));
    }

    return response.data;
  });

相关问题