让Axios从React使用Spring Boot+Spring Boot Security



我已经创建了一个带有spring-boot后端的react应用程序,但我在使用axios获取数据时遇到了问题。

我已经检查了许多SO的帖子以及spring的文档,但都没有结果。我最初被CORS阻止,但我通过Spring Security解决了这个问题。然而,spring安全性需要身份验证,我一直在使用默认的用户"用户";使用随机生成的密码(因为我无法获得用AuthenticationManagerBuilder定义的新定义的用户/密码来直接在浏览器中处理针对服务器的查询,但这是另一天的问题)。下面是我的服务器配置文件。

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {

http
.authorizeRequests()
.anyRequest().authenticated()
.and()            
.httpBasic();
http.cors().and();
}    
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
configuration.setAllowedMethods(Arrays.asList("GET", "PUT", "POST", "DELETE", "OPTIONS", "HEAD"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}

我的服务器运行在localhost端口9898上,我最初试图从前端提取数据的查询是联系人信息的get-by-id,这与http://localhost:9898/api/Contact/1当我从浏览器直接成功调用服务器时,标头详细信息如下所示:从浏览器到服务器的调用常规和响应标头从浏览器到服务器的调用请求头

请注意,授权头实际上就在请求中。

对于RestController,我已经将交叉原点设置为在端口3000上运行的客户端。正如教程中所建议的,我确实在getContactMethod中添加了一个头,但我认为这实际上没有改变任何东西,因为我在配置文件中设置了这个头。

@CrossOrigin(origins = "http:localhost:3000")
@RestController
@RequestMapping("/api/Contact")
public class ContactController {

@Autowired
private ContactRepository ContactRepository;
@GetMapping("/")
public List<Contact> getContacts(){
return this.ContactRepository.findAll();
}
@GetMapping("/{id}")
public Contact GetContact(@PathVariable Long id, HttpServletResponse response){
response.setHeader("Access-Control-Allow-Origin", "**");
return ContactRepository.findById(id).orElse(null);
}

对于客户端,我有一个创建axios实例的文件,我不确定这部分是否正确,因为我再也没有引用过特定的实例,但如果只有一个实例,axios可能会自己解决这个问题。

import axios from "axios";
const api = axios.create({
baseURL: "http://localhost:9898",
});
// api.defaults.headers.common = {
//     'X-Requested-With': 'XMLHttpRequest'
// };
export default axios;

现在,对于前端的实际页面,我试图将请求的数据从useEffects事件加载到状态变量中,这需要进一步修改,但在请求工作之前,我无法继续执行。

根据我在网上看到的内容,我已经加载了许多头文件,但我想重点关注的是身份验证,因为当我在网络上使用开发工具时,这实际上不会显示在请求中。我得到了每次后台运行硬编码时由spring-security随机设置的密码,然后这个硬编码的user:password值被编码并添加到头中。以下是相关代码:

const tok = 'user:9de3a921-a4af-4d51-b8d7-cf37b208916e';
const hash = btoa(tok);
const Basic = 'Basic ' + hash;
const headers = {
"Cache-Control": "no-cache",
"Accept-Language": "en",
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "http://localhost:3000",
"Access-Control-Allow-Methods": "DELETE, POST, GET, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization, X-Requested-With",
//"Authorization": "Basic dXNlcjowM2VhN2JhYS1mMTQ0LTQ5YWMtOGFhMy02NDE4YWJiNzdhMTk=",
'Authorization': `Basic ${hash}`,
};
useEffect(() =>{
console.log(Basic);
axios.get("http://localhost:9898/api/Contact/1", headers)
.then((res) => {
console.log("data " + res.data);
console.log("response header " + res.headers['Authorization']);
setInfo(res.data);
}).catch(err => console.log("error found " + err));
console.log(info);
}, []||[]);

当它运行时,我得到一个401未经授权的消息,但由于某种原因,授权标头没有显示在请求标头中。

从客户端到服务器的请求的常规和响应标头

从客户端到服务器的请求标头

我觉得我已经很接近了,但spring网站上的大多数教程都更简单,而且多年来spring安全的最佳实践也发生了变化,所以网上有很多相互矛盾的信息和不完整的例子。我想我要么在安全配置方面有问题,要么我想我设置的标题不正确,但我对spring和react没有足够的经验,我刚刚在圈子里进行了几天的故障排除。

消息来源已经尝试过了(必须在链接中放一些空格,因为我刚刚创建了这个帐户来发布一个问题):

https://stackoverflowcom/questions/36968963/如何配置弹簧中的弹簧弹簧安全应用程序/37610988#37610988

我应该在下面提到我在.antMatchers(HttpMethod.Options,"/**&").permitAll()中添加的这个,头文件不同,但请求仍然不起作用,最终服务器在启动后不久就会崩溃

https://stackoverflowcom/quests/41075850/如何在spring-boot中配置cors和基本授权/60933851#60933851

https://stackoverflowcom/questions/58901586/如何修复未通过的弹簧安全授权标头

https://springio/blog/2022/02/21/spring-security不带websecurityconfigeradapter

https://springio/导游/gs/休息服务cors/

https://springio/导游/gs/休息服务/

https://docs.springio/spring security/reference/reflective/integrations/cors.html

https://www.baeldungcom/spring-security-cors飞行前

如何将标头传递到axios存在问题。axios文档对axios.get的定义与axios.get(url[, config])类似

这里有两个参数。第一个是url,它是必需的。第二个是可选的配置对象。

config对象有一个headers字段。

你应该这样传递标题:

const headers = {
'Cache-Control': 'no-cache',
'Accept-Language': 'en',
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': 'http://localhost:3000',
'Access-Control-Allow-Methods': 'DELETE, POST, GET, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Requested-With',
//"Authorization": "Basic dXNlcjowM2VhN2JhYS1mMTQ0LTQ5YWMtOGFhMy02NDE4YWJiNzdhMTk=",
Authorization: `Basic ${hash}`
};
const config = {
headers
};
axios.get('http://localhost:9898/api/Contact/1', config);

我回顾了我之前提到的类似帖子如何在SpringBoot+SpringSecurity应用程序中配置CORS?我在2021年3月11日试用了用户Soroosh Khodami更新次数第四的答案,并使用了他们的SecurityConfig。

@Override
protected void configure(HttpSecurity http) throws Exception {
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"));

// You can customize the following part based on your project, it's only a sample
http.authorizeRequests().antMatchers("/**").permitAll().anyRequest()
.authenticated().and().csrf().disable().cors().configurationSource(request -> corsConfiguration);
}

我以前的配置不见了:

  1. setAllowedHeaders(Listof("Authorization",..))
  2. setAllowCredentials(true)
  3. setExposedHeaders(授权)

这将导致我进入第二个issed,这是由于在我的restcontroller get-by-id方法中设置了头引起的。

response.setHeader("Access-Control-Allow-Origin", "**");

我得到了一个错误,说这是不允许的,所以我把它改成了"/**"它仍然抱怨,所以我只是评论了一下,它起了作用。因此,如果有教程建议这样做(对我来说,这是一个关于让cors工作的youtube视频),我认为在Web安全配置中设置访问控制允许起源已经过时/不是最佳做法。

相关内容

  • 没有找到相关文章

最新更新