Spring boot:无法从另一个 Origin 访问安全资源 - CORS - Spring Security - Spring data rest

Posted

技术标签:

【中文标题】Spring boot:无法从另一个 Origin 访问安全资源 - CORS - Spring Security - Spring data rest【英文标题】:Spring boot: Can not access secured resource from another 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 问题。见***.com/a/42021652/5277820 【参考方案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 调用)并允许它在没有任何安全性的情况下通过。

【讨论】:

以上是关于Spring boot:无法从另一个 Origin 访问安全资源 - CORS - Spring Security - Spring data rest的主要内容,如果未能解决你的问题,请参考以下文章

无法在 Spring Boot 应用程序提供的响应中设置“Access-Control-Allow-Origin”标头

如何从另一个新的 Spring Boot 项目调用一个 Spring Boot 项目中存在的 Spring Boot api

如何从另一个 Spring Boot 应用程序访问一个 Spring Boot 应用程序的内存 H2 数据库

无法在 Spring Boot 应用程序中读取 application.properties

CORS Origin 失败的 Spring Boot

从另一个 Spring Boot JPA 项目插入的数据库中读取数据