在阅读了 CORS 上的所有 MDN 文档后,我试图从 localhost:3000 的 ReactJS 应用程序在 localhost:8080 的 spring boot 服务器上获取资源,但我无法获得所需的响应。这是 spring boot 配置
...
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors();
http.authorizeRequests().antMatchers(
// "/registration**",
"/js/**", "/css/**", "/img/**", "/api/**", "/webjars/**").permitAll()
.antMatchers("/calendar", "/calendar-delete", "/calendar-edit", "/calendar-addEvent",
"/calendar-updateEvent", "/contacts", "/contact-edit", "/jobs/jobs-list", "/job-new",
"/applicants/applicants-list", "/applicant-new", "/", "/index", "/task-list", "/task-assign",
"/tasks-pending", "/task-approve", "/task-deny", "/profile", "/upload-avatar", "/users",
"/settings", "/appsettings", "/changepassword", "/messages", "/message", "/message-new",
"/message-to", "/h2-console/**")
.permitAll().antMatchers("/admin/**")
.hasAuthority("ROLE_ADMIN").antMatchers("/activites/**")
.hasAnyAuthority("ROLE_ADMIN","ROLE_COLLABORATEUR").and().formLogin().loginProcessingUrl("/api/login").permitAll()
.and()
.formLogin().failureHandler(customAuthenticationFailureHandler())
.and().formLogin().successHandler(successHandler())
.and()
.logout()
.invalidateHttpSession(true).clearAuthentication(true)
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login?logout")
.permitAll();
http.csrf().disable();
}
@Bean
public CustomSuccessHandler successHandler() {
return new CustomSuccessHandler();
}
....
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
configuration.addAllowedHeader("*");
configuration.setAllowCredentials(false);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
这是负责处理请求的控制器方法
@GetMapping("/api/plot")
@ResponseBody
public List<StatisticBesoin> plot(@RequestParam("date") int year) {
return this.besoinService.getStatistic(year);
}
这是 Reactjs 登录组件,请注意,按下登录按钮后,我会收到所需的 json 响应和 set-cookies jssid
const Login = (props) => {
const navig = useNavigate();
const [userName,setUserName] = useState("");
const [password,setPassword] = useState("");
function authenticate(usr,pswrd){
var data = new URLSearchParams();
data.append('username', usr);
data.append('password', pswrd);
fetch("http://localhost:8080/api/login",{
headers:{
"Content-type": "application/x-www-form-urlencoded",
},
method:"post",
body:data
}).then(response => response.json()).then(usr => {props.setUser(usr);console.log(usr);navig('/homme')});
}
return(
<div className='wrapper'>
<div className='login'>
<div className='header'>Login</div>
<div className="form-control"><i className="fa fa-user" aria-hidden="true"></i><input onChange={(e)=>setUserName(e.target.value)} name="userName" id="userName" type="text" placeholder="User name" /></div>
<div className="form-control"><i className="fa fa-lock" aria-hidden="true"></i><input onChange={(e)=>setPassword(e.target.value)} name="userName" id="userPassword" type="password" placeholder="Password" /></div>
<div className="form-control"><input type="button" value="Login" onClick={()=>authenticate(userName,password)}/></div>
</div>
</div>
)
}
在我的问题所在的主页旁边:
const Home = (props) => {
function plot(){
fetch('http://localhost:8080/api/plot')
.then(resp => resp)
.then(t => {console.log(t)})}
return(
<div className='wrapper'>
<input type="button" value="call" onClick={plot}/>
{props.usr.toString()}
</div>
)
}
按下按钮后的反应是ò
body: (...)
bodyUsed: false
headers: Headers
[[Prototype]]: Headers
ok: true
redirected: true
status: 200
statusText: "OK"
type: "cors"
url: "http://localhost:8080/login"
我尝试了从将允许的来源设置为“*”到将请求中的 allow-credentials 标头设置为“包含”的所有方法,但都是徒劳的。请注意,我可以看到与 /plot 请求一起发送的 jssid cookie,所以我想我的身份验证没有问题。有人可以找出问题所在吗?我认为问题的所有资源都可用,但如果需要我会提供任何其他资源?
回答1
如果这是一个本地开发环境,通过使用以下属性增强您的 React 应用程序 package.json
来启用 https://create-react-app.dev/docs/proxying-api-requests-in-development/ 的代理功能通常就足够了:
"proxy": "http://localhost:8080"
然后,将您的 Ajax 请求从您的 React 应用程序发送到 /your/api/path
而不是 http://localhost:8080/your/api/path
并且开发网络服务器会将 Ajax 请求代理到提供的地址,并且您的浏览器不会抱怨 CORS。
您不需要在 Spring 引导应用程序中配置任何特定的 CORS 支持。
稍后,当应用程序部署在 web 服务器上时,这通常不再是问题,因为两者都将在同一主机上提供服务,然后 Ajax 请求由主机上的 web 服务器代理到后端,该服务器为入站请求提供服务。