Spring Boot Security模块在使用来自react的axios调用时给出403错误,但在poster中运行



我有一个spring-boot项目,它使用带有JWT令牌的spring-security。这在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());
}

React 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实例时,似乎在标头中错过了Authorization

我认为问题就在这里:

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

您将spring-to-permitAll请求告知/authenticate/端点,并要求对所有其他请求进行身份验证。但在前端,您正在向/CRUD/authenticate/提出请求。这就是为什么您得到403,因为该路径必须经过身份验证——这意味着请求必须已经具有Authorization头。我认为如果你把第一行改为,它应该会起作用

.csrf().disable().authorizeRequests().antMatchers("/CRUD/authenticate/")

最新更新