【问题标题】:Spring boot: Can not access secured resource from another Origin - CORS - Spring Security - Spring data restSpring boot:无法从另一个 Origin 访问安全资源 - CORS - Spring Security - Spring data rest
【发布时间】:2018-09-07 03:36:33
【问题描述】:

我无法从另一个 Origin 访问受保护的资源。找了几天没找到,所以在这里发帖提问。

故事是这样的:

我创建了第一个在默认端口 8080 上运行的 Spring Boot 应用程序。

它依赖于 spring-boot-starter-data-rest 和其他依赖,它有一个 GreetingRepository:

public interface GreetingRepository extends JpaRepository<Greeting, Long>, JpaSpecificationExecutor<Greeting> {}

使用 RepositoryRestConfigurerAdapter 全局启用 CORS:

@Configuration 
public class GlobalRepositoryRestConfigurer extends RepositoryRestConfigurerAdapter {

@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
    config.getCorsRegistry()
            .addMapping("/**")
            .allowedOrigins("*")
            .allowedHeaders("*")
            .allowedMethods("*");
}
}

我创建了在端口 9000 上运行的第二个 Spring Boot 应用程序,它将访问此 Greetings 资源。

而且它有效。第二个应用程序使用 GET 方法向http://localhost:8080/api/greetings 发送 HTTP 请求,并获得带有 Json 数据的响应,HEADER Access-Control-Allow-Origin: *.一切都很好。

但是。

然后我想在第一个应用程序中保护我的资源。在那里我包含了 spring-boot-starter-security 依赖项并在 WebSecurityConfigurerAdapter 中进行了配置:

@EnableWebSecurity 
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsService myUserDetailsService;

@Autowired
PasswordEncoder myPasswordEncoder;

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .formLogin().permitAll()
            .and()
            .httpBasic()
            .and()
            .csrf().disable();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(myUserDetailsService).passwordEncoder(myPasswordEncoder);
}

@Bean
public UserDetailsService createBeanUserDetailService() {
    return new MyUserDetailsService();
}

@Bean
public PasswordEncoder createBeanPasswordEncoder() {
    return new BCryptPasswordEncoder();
}
}

并制作了 UserDetailsS​​ervice 等等。 (重要提示:我在添加 CORS 之前测试了安全性,因此此安全配置有效,这不是问题

然后,在第一个应用程序中添加安全性后,第二个应用程序使用 GET 方法向http://localhost:8080/api/greetings 发送与第一次相同的 HTTP 请求。

现在出现错误Failed to load http://localhost:8080/api/greetings: Redirect from 'http://localhost:8080/api/greetings' to 'http://localhost:8080/login' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access.

我找不到这个问题的解决方案。因此 CORS 适用于 Spring Repository 资源,而 Spring Security 适用,但由于 /login 页面,我无法从另一个 Origin 访问安全资源。如何解决?

【问题讨论】:

  • 你没有登录,所以你被重定向到你的登录页面。
  • 如果您的 REST 调用未通过身份验证,您真的想查看登录页面吗?
  • @dur 我知道我为什么会被重定向。我想构建可以从另一个 Origin(其他网站和移动应用程序)访问的 API。例如,如何使用 Ajax 验证来自另一个 Origin 的请求?我使用基本身份验证。
  • 您的第一个问题是,您的请求未通过身份验证。您确定您的请求包含基本身份验证吗?用户名和密码是否正确?显示带有标头的请求。在解决了第一个问题之后,您还必须解决 CORS 问题。
  • 现在您解决了 CORS 问题。见stackoverflow.com/a/42021652/5277820

标签: rest spring-boot spring-security cors spring-data-rest


【解决方案1】:

启用 Spring 安全时,安全过滤器优先于 CorsFilter。要让 Spring Security 了解您的 CORS 配置,请在您的 HttpSecurity 设置中调用 cors() 方法。

@Override
protected void configure(HttpSecurity http) throws Exception {
  http
        .cors()
        .and()
        .authorizeRequests()
        .anyRequest().authenticated()
        .and()
        .formLogin().permitAll()
        .and()
        .httpBasic()
        .and()
        .csrf().disable();
}

这将使CorsFilter 优先于其他 Spring 安全过滤器。 CorsFilter 识别 CORS 预检请求(HTTP OPTIONS 调用)并允许它在没有任何安全性的情况下通过。

【讨论】:

    猜你喜欢
    • 2019-03-04
    • 2017-04-22
    • 2020-04-10
    • 2019-07-16
    • 2016-12-04
    • 2017-03-10
    • 2018-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多