Java 由于CORS,Spring安全注销不工作
技术:Spring Security、后端的Spring Boot以及前端的ReactJs和axios 我想要什么:在我的前端点击Java 由于CORS,Spring安全注销不工作,java,spring,spring-security,axios,Java,Spring,Spring Security,Axios,技术:Spring Security、后端的Spring Boot以及前端的ReactJs和axios 我想要什么:在我的前端点击注销按钮时,我想注销用户。为此,我使用delete调用后端。然后我希望我的后端注销 我的问题:当我从我的前端调用Spring Security注销端点时,我收到以下消息: 加载失败http://localhost:8080/logout: 对飞行前请求的响应未通过访问控制检查:请求的资源上不存在“访问控制允许来源”标头。起源'http://localhost:8888
注销
按钮时,我想注销用户。为此,我使用delete
调用后端。然后我希望我的后端注销
我的问题:当我从我的前端调用Spring Security注销
端点时,我收到以下消息:
加载失败http://localhost:8080/logout: 对飞行前请求的响应未通过访问控制检查:请求的资源上不存在“访问控制允许来源”标头。起源'http://localhost:8888因此,不允许访问。响应的HTTP状态代码为403。
我确实理解出现此错误的原因-后端在localhost:8080上,前端在localhost:8888上。但我不理解的是,为什么我的配置不适用于注销,而在所有其他情况下(例如,调用spring securitylogin
endpoint或我的一些自定义endpoint)它工作得非常好
我如何从前端拨打电话
const endpoint = 'logout';
return axios.delete(
'http://localhost:8080/' + `${endpoint}`,
{withCredentials: true}
)
.then(response => {
let resp = {
httpCode: response.status,
data: response.data
};
return {response: resp};
})
.catch(error => {
let err = {
httpStatusCode: error.response.status,
message: `Error calling endpoint ${endpoint}`
};
return {error: err};
});
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("http://localhost:8888");
}
};
}
从前端启用CORS
const endpoint = 'logout';
return axios.delete(
'http://localhost:8080/' + `${endpoint}`,
{withCredentials: true}
)
.then(response => {
let resp = {
httpCode: response.status,
data: response.data
};
return {response: resp};
})
.catch(error => {
let err = {
httpStatusCode: error.response.status,
message: `Error calling endpoint ${endpoint}`
};
return {error: err};
});
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("http://localhost:8888");
}
};
}
SecurityConfig.java-在这里,您可能会注意到一些部分被注释了-它们是我尝试过的其他解决方案,但它们不起作用
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@EnableJpaRepositories(basePackageClasses = UsersRepository.class)
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService userDetailsService;
@Autowired
private RESTAuthenticationEntryPoint restAuthenticationEntryPoint;
@Autowired
private RESTAuthenticationSuccessHandler restAuthenticationSuccessHandler;
@Autowired
private RESTAuthenticationFailureHandler restAuthenticationFailureHandler;
@Bean
public CustomLogoutHandler customLogoutHandler(){
return new CustomLogoutHandler();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(getPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf().disable()
.authorizeRequests()
.antMatchers("**/anna/**").authenticated()
.anyRequest().permitAll()
.and()
.logout()
.addLogoutHandler(customLogoutHandler())
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
http.exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint);
http.formLogin().successHandler(restAuthenticationSuccessHandler);
http.formLogin().failureHandler(restAuthenticationFailureHandler);
// http
// .logout()
// .logoutUrl("/logout")
// .addLogoutHandler(new CustomLogoutHandler())
// .invalidateHttpSession(true);
// http
// .cors()
// .and()
// .csrf().disable()
// .logout()
// .logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
private PasswordEncoder getPasswordEncoder() {
return new PasswordEncoder() {
@Override
public String encode(CharSequence charSequence) {
return charSequence.toString();
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return true;
}
};
}
}
CustomLogoutHandler.java我在某个地方读到了关于在这里设置标题的解决方案。我想这是一种不好的做法,我宁愿不这样做,但基本上我很高兴看到日志工作。目前它没有记录任何东西,所以我猜它在注销时没有被调用
//@Slf4j
public class CustomLogoutHandler implements LogoutHandler{
@Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication){
response.setHeader("Access-Control-Allow-Origin", "*");
System.out.println("TodosLogoutHandler logging you out of the back-end app.");
}
}
我检查了的源代码 如您所见,默认情况下,
Delete
方法是不允许的,因此您需要添加Delete
方法
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:8888")
.addAllowedMethod(HttpMethod.DELETE);
}
};
}
为什么要使用
删除/注销
?在我看来,这完全出乎意料,离最佳实践相去甚远。在/注销时没有可删除的资源。我建议POST/logout
或DELETE/session
。谢谢您的建议。我将使用POST/logout
。这就是问题所在。多谢各位!