Spring Boot Security 模块在使用来自 React 的 axios 调用时给出 403 错误,但在邮递员中工作正常

Spring Boot Security module gives 403 error when called by using axios from react but works fine in postman

我有一个 spring 引导项目,它使用 spring 安全性和 JWT 令牌。这在 POSTMAN 中工作正常,但在使用 react axios 时会出现 403 错误。 下面是使用的代码

SecurityConfig.java

    package com.cg.practice.EmployeeCRUD.config;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.config.BeanIds;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.config.http.SessionCreationPolicy;
    import org.springframework.security.crypto.password.NoOpPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
    import org.springframework.web.cors.CorsConfiguration;
    
    import com.cg.practice.EmployeeCRUD.Service.CustomUserService;
    import com.cg.practice.EmployeeCRUD.filter.EmployeeCRUDFilter;
    
    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        CustomUserService userService;
        
        @Autowired
        EmployeeCRUDFilter employeeCRUDFilter;
        
        /*
         * @Autowired CorsFilter corsFilter;
         */
    
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            // TODO Auto-generated method stub
            System.out.println("Hi1");
            auth.userDetailsService(userService);
        }
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return NoOpPasswordEncoder.getInstance();
        }
    
        @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
    
            @Override
        protected void configure(HttpSecurity http)  {
            // TODO Auto-generated method stub
            System.out.println("Hi2");
              try { 
                  CorsConfiguration corsConfiguration = new CorsConfiguration();
                    corsConfiguration.setAllowedHeaders(List.of("Authorization", "Cache-Control", "Content-Type"));
                    corsConfiguration.setAllowedOrigins(List.of("http://localhost:3000"));
                    corsConfiguration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PUT","OPTIONS","PATCH", "DELETE"));
                    corsConfiguration.setAllowCredentials(true);
                    corsConfiguration.setExposedHeaders(List.of("Authorization"));
                  
                  http
                 // .addFilterBefore(corsFilter, SessionManagementFilter.class) 
                  .csrf().disable().authorizeRequests().antMatchers("/authenticate/")
                  .permitAll().anyRequest().authenticated()
                  .and().exceptionHandling().and().sessionManagement()
                  .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                  .and().cors().configurationSource(request -> corsConfiguration);
    ;
          http.addFilterBefore(employeeCRUDFilter, UsernamePasswordAuthenticationFilter.class);
                  } 
              catch (Exception e) 
              { 
                      // TODO: handle exception 
                      e.printStackTrace(); 
                      }
                  }
             
        }

EmployeeCRUDFilter.java

package com.cg.practice.EmployeeCRUD.filter;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import com.cg.practice.EmployeeCRUD.Service.CustomUserService;
import com.cg.practice.EmployeeCRUD.util.JwtUtil;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;

@Component
public class EmployeeCRUDFilter extends OncePerRequestFilter {

    @Autowired
    JwtUtil jwtUtil;
    @Autowired
    CustomUserService userService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            {
        // TODO Auto-generated method stub
        String authorizationHeader = request.getHeader("Authorization");

        String token = null;
        String userName = null;
try
{
        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            token = authorizationHeader.substring(7);
            userName = jwtUtil.extractUsername(token);
        }

        if (userName != null && SecurityContextHolder.getContext().getAuthentication() == null) {

            UserDetails userDetails = userService.loadUserByUsername(userName);

            if (jwtUtil.validateToken(token, userDetails)) {

                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                        new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken
                        .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }
        filterChain.doFilter(request, response);
    }   
catch (Exception e) {
    // TODO: handle exception
    e.printStackTrace();
}
            }
    }

CRUD控制器方法

@PostMapping("/authenticate")
    
    public String generateToken(@RequestBody AuthRequest authRequest) throws Exception
    {

        try {
        authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(
                authRequest.getUserName(),authRequest.getPassword())        
                        );
        }
        catch (Exception e) {
            return "Invalid User/Password";
        }
        return jwtUtil.generateToken(authRequest.getUserName());
    }

反应 Authservice.js

import http from '../Mycomponent/http-common';

class AuthService{

    authenticate(){
        return http.post("/authenticate", {"userName":"Dip","password":"password@123"}
        )
        .then(response => {
            console.log(response.data)
            if (response.data.accessToken) {
              localStorage.setItem("user", JSON.stringify(response.data));
            }
            return response.data;
          })
          .catch(error =>{
            console.log("Error :"+error);
          });
    }
}
export default new AuthService();

http-common.js

import axios from 'axios';

export default axios.create({
  baseURL: "http://localhost:8080/CRUD",
  headers: {
    "Content-type": "application/json"
      }
});

这会在浏览器中产生 403 错误

Failed to load resource: the server responded with a status of 403 ()
AuthService.js:16 Error :Error: Request failed with status code 403
:8080/CRUD/getAll:1          Failed to load resource: the server responded with a status of 403 ()
createError.js:16 Uncaught (in promise) Error: Request failed with status code 403
    at createError (createError.js:16:1)
    at settle (settle.js:17:1)
    at XMLHttpRequest.onloadend (xhr.js:66:1)

谁能帮忙。我坚持了很长时间。我错过了什么吗?我是新来的反应。

在 PostMAN 中工作正常

似乎您在设置 axios 实例时错过了 header 中的 Authorization

我认为问题出在这里:

http
    .csrf().disable().authorizeRequests().antMatchers("/authenticate/")
    .permitAll().anyRequest().authenticated()
    .and().exceptionHandling().and().sessionManagement()
    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    .and().cors().configurationSource(request -> corsConfiguration);

您告诉 spring 将 permitAll 请求发送到 /authenticate/ 端点,并要求对所有其他请求进行身份验证。但是从前端您正在向 /CRUD/authenticate/ 发出请求。这就是您得到 403 的原因,因为此路径必须经过身份验证 - 这意味着请求必须已经具有 Authorization header。如果将第一行更改为:

,我认为它应该可以工作
.csrf().disable().authorizeRequests().antMatchers("/CRUD/authenticate/")