【问题标题】:Unable to fix CORS issue with Spring Boot and Angular [duplicate]无法使用 Spring Boot 和 Angular 修复 CORS 问题 [重复]
【发布时间】:2020-07-19 06:15:29
【问题描述】:

我是 Spring Boot 和 Angular 的新手,正在努力解决 CORS 问题。

我想实现一个全局 CORS 过滤器并尝试实现 CorsFilter、WebMvcConfigurer 并尝试使用 WebMvcConfigurerAdapter 类,但这些方法似乎都不起作用。我知道我错过了一些东西,但不知道是什么。如果有人可以在我的代码中找到解决方案,那将是很大的帮助。

如果有帮助的话,我还实现了基本身份验证并添加了该代码。

这是我的代码。

Angular API 调用

api.service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class ApiService {

  constructor(private httpClient: HttpClient) { }

  userLogin(username: String, password: String) {
    let postBody = {
      "username" : username,
      "password" : password
    };
    let httpOptions = {
      headers : new HttpHeaders({
        "Content-Type" : "application/json",
        "Authorization" : "Basic " + btoa('myUsername:myPassword')
      })
    }
    return this.httpClient.post("http://localhost:8080/userLogin", postBody, httpOptions);
  }

}

这是我的 API 代码。

MainApp.java

@SpringBootApplication
public class MainApp extends SpringBootServletInitializer {
    public static void main(String... str) {
        SpringApplication.run(MainApp.class, str);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(MainApp.class);
    }

}

Config.java

@Configuration
public class Config {

    @Bean
    public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowCredentials(true);
        configuration.setAllowedOrigins(Collections.singletonList("*"));
        configuration.setAllowedHeaders(Arrays.asList("Origin", "Content-Type", "Accept"));
        configuration.setAllowedMethods(Arrays.asList("POST"));
        source.registerCorsConfiguration("/**", configuration);
        return new CorsFilter(source);
    }
}

NotebookController.java

@RestController
public class NotebookController {

    @Autowired
    IUsersRepo usersRepo;
    @Autowired
    INotesRepo notesRepo;

    @PostMapping("userLogin")
    @ResponseBody
    public ResponseEntity<String> userLogin(@RequestParam("username") String username, @RequestParam("password") String password) {
        ObjectWriter objectWriter = new ObjectMapper().writer().withDefaultPrettyPrinter();
        List<Users> usersList = usersRepo.findByUsernameEqualsAndPasswordEquals(username, password);
        boolean userVerified = usersList.size() > 0 ? true : false;
        HashMap<String, Boolean> outputMap = new HashMap<>();
        outputMap.put("authenticated", userVerified);
        String outputJson = "";
        try {
            outputJson = objectWriter.writeValueAsString(outputMap);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        outputJson = outputJson.toString();
        ResponseEntity<String> response = new ResponseEntity<String>(outputJson, HttpStatus.OK);
        return response;
    }
}

Authentication.java

@Configuration
@EnableWebSecurity
public class Authentication extends WebSecurityConfigurerAdapter {

    @Autowired
    AuthenticationEntryPoint authEntryPoint;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.cors().and().csrf().disable();

        //Authorise all incoming requests
        http.authorizeRequests().and().httpBasic();
        http.authorizeRequests().anyRequest().authenticated();

        //Use AuthenticationEntryPoint to authorise username/password
        http.httpBasic().authenticationEntryPoint(authEntryPoint);
    }

    @Bean
    public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowCredentials(true);
        configuration.setAllowedOrigins(Collections.singletonList("*"));
        configuration.setAllowedHeaders(Arrays.asList("Origin", "Content-Type", "Accept"));
        configuration.setAllowedMethods(Arrays.asList("POST"));
        source.registerCorsConfiguration("/**", configuration);
        return new CorsFilter(source);
    }

    @Bean
    public BCryptPasswordEncoder getEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        String username = "myUsername";
        String password = "myPassword";

        InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> mngConfig = authenticationManagerBuilder.inMemoryAuthentication();

        mngConfig.withUser(username).password(password).roles("USER");
    }

}

AuthEntryPoint.java

@Component
public class AuthEntryPoint extends BasicAuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException authException) throws IOException, ServletException {
        super.commence(request, response, authException);
        response.addHeader("WWW-Authenticate", "Basic realm=" + getRealmName());
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        PrintWriter writer = response.getWriter();
        writer.println("HTTP Status 401: Unauthorised | " + authException.getMessage());
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        setRealmName("Online Notebook");
        super.afterPropertiesSet();
    }

}

请同时查看浏览器控制台。

https://imgur.com/a/hHceJDw

【问题讨论】:

  • imgur.com/a/hHceJDw 的图像中显示的错误消息说,“预检响应中的访问控制允许标头不允许请求标头字段“授权”” .所以你需要改变你的代码来拥有configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type"))。请不要将错误消息的屏幕截图发布到 Stack Overflow 的问题中。始终以文本形式复制并粘贴错误消息。
  • @sideshowbarker 非常感谢您的帮助。有效。我也会考虑你的建议。

标签: java angular spring spring-boot cors


【解决方案1】:

由于您使用的是 spring security ,因此您可以像下面这样配置 cors 和 spring security ,以便飞行前检查请求通过 spring security。

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and()
            //other configurations that you want
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource()
    {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        //or any domain that you want to restrict to 
        configuration.setAllowedHeaders(Arrays.asList("Origin", "Content-Type", "Accept","Authorization"));
   configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        //Add the method support as you like 
        UrlBasedCorsConfigurationSource source = new     UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

您可能面临的问题是 Spring Security 不会让飞行前检查请求通过并使其失败。如需更多分析,请分享您的浏览器日志或请求中的错误。

从浏览器错误中可以看出,cors 配置不允许您添加到请求的标头 "Authorization",因为您在 cors 配置中仅指定了标头 "Origin", "Content-Type", "Accept"。将 "Authorization" 标头也添加到 cors 配置中,问题应该得到解决。

【讨论】:

  • 我按照您的建议进行了尝试,但仍然遇到同样的错误。我已按照建议更新了 Authentication.java 文件,并在问题中也对其进行了更新。我还在最后添加了浏览器输出。
  • 我也尝试删除 csrf 安全,但效果不佳。
  • @ChiranjeevJain 将授权标头添加到 configuration.setAllowedHeaders(Arrays.asList("Origin", "Content-Type", "Accept")); ,它将解决您的问题
猜你喜欢
  • 2021-03-15
  • 1970-01-01
  • 2020-09-08
  • 2019-12-16
  • 2018-10-30
  • 2017-04-13
  • 2019-09-16
  • 2022-10-07
  • 2021-09-26
相关资源
最近更新 更多