java - Spring boot CORS 过滤器不适用于 AngularJS

标签 java angularjs spring-boot cors activiti

我创建了一个具有 AngularJS 前端的 SpringBoot 应用程序,但我没有使用任何 Spring Security 模块。

我已经在我的 Controller 中添加了@CrossOrigin注解,如下所示

@CrossOrigin(origins = "http://localhost:3000", maxAge = 3600)
@RestController
public class MyController {
   public static final Logger logger = LoggerFactory.getLogger(MyController.class);
   .....
   .....

我还创建了一个 CORS 过滤器,如下所示。

@Component
public class CORSFilter implements Filter {

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    HttpServletResponse response = (HttpServletResponse) res;
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    chain.doFilter(req, res);
}

public void init(FilterConfig filterConfig) {}
public void destroy() {}

我的 angularJS 前端中的 OPTIONS 出现以下错误

XMLHttpRequest cannot load http://localhost:8080/abc/books/. Response for preflight has invalid HTTP status code 401 (edited)

[12:10] 
zone.js:2744 OPTIONS http://localhost:8080/abc/books/ 401 ()

我的 SpringBoot 应用程序可以与 PostMan 一起正常工作,并且当我使用 Chrome 时会发生此预检错误。我该如何解决?

编辑

我还使用了 activiti-spring-boot-starter-rest-api,它有以下内容:

import org.activiti.engine.IdentityService;
import org.activiti.engine.identity.User;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class AuthenticationService {

@Bean
InitializingBean usersAndGroupsInitializer(final IdentityService identityService) {

    return new InitializingBean() {
        public void afterPropertiesSet() throws Exception {
            User admin = identityService.newUser("admin");
            admin.setPassword("admin");
            identityService.saveUser(admin);
            }
        };
    }

最佳答案

如评论中所述,问题是 activiti-spring-boot-starter-rest-api 具有开箱即用的安全性。这里的问题是他们在根上下文上应用了安全性,这意味着任何其他端点也将具有身份验证。

选项 1:添加您自己的安全性

要解决这个问题,您可以创建自己的具有更高优先级的 SecurityConfig 类,并允许所有请求转到 /abc/**(或其他任何内容),例如:

@Order(Ordered.HIGHEST_PRECEDENCE) // This should "overrule" Activiti's security
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/abc/**")
            .authorizeRequests().anyRequest().permitAll();
    }
}

选项 2:禁用 Activiti 的安全性

或者,您可以禁用 Activiti 的安全自动配置:

@EnableAutoConfiguration(exclude = {
    org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration.class,
    org.activiti.spring.boot.SecurityAutoConfiguration.class
})

这将禁用 Activiti 和 Spring boot 本身的安全自动配置。如果您只禁用 Activiti 的安全配置,Spring boot 的自动配置将启动,您仍然可以在所有端点上进行身份验证。

但是,您可能仍想在 Activiti 的某些端点上应用安全性,但这允许您自己自定义它,而不是依赖自动配置。在您的情况下,您可以选择对所有 /identity/**/management/**/history/** 应用安全性, /repository/**, /query/**/runtime/** 路径,Activiti正在使用这些路径。


选项 3:在 OPTIONS

的情况下覆盖过滤器链

第三种选择是绕过整个安全过滤器链。如图this answer ,您可以通过不调用 chain.doFilter(req, res) 来打破过滤器链。这可以通过在过滤器中添加以下内容来完成:

if (HttpMethod.OPTIONS.name().equalsIgnoreCase(req.getMethod()) {
    res.setStatus(HttpServletResponse.SC_OK);
} else {
    chain.doFilter(req, res); // Only apply doFilter() when not OPTIONS
}

NOTE: Be aware though, this will only allow the OPTIONS call to go through. The security also affects the other endpoints you defined in your controller, and not just the OPTIONS call.

通过有条件地调用 doFilter(),您可以跳过整个安全过滤器链,以防出现 OPTIONS 请求。您必须转换 reqres 分别为 HttpServletRequestHttpServletResponse

此外,您必须确保此过滤器在安全过滤器链之前被调用。为此,请将 CORSFilter 的顺序更改为选定的值,例如:

@Component
@Order(1) // You can choose the value yourself
public class CORSFilter implements Filter {
    // ...
}

现在通过将 application.properties 中的 security.filter-order 属性设置为更高的值来更改安全过滤器链顺序:

security.filter-order=2

关于java - Spring boot CORS 过滤器不适用于 AngularJS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46461478/

相关文章:

javascript - 仅当单击“保存”按钮时才导入 csv(添加了 Plunker)

javascript - 在UI端进行数值计算可以吗?

java - 如何使用 Spring Boot 让多个线程从 RabbitMQ 队列中获取数据?

java - C++ 中的头文件和Java 中的抽象类/接口(interface)实现是同一个想法吗?

java - Derby EmbeddedDriver 在没有 Class.forName 的情况下工作

java - Android - 光标找不到列

java - 是否可以将依赖项 CDI 与 Wildfly 一起使用?

javascript - 如何确定对象内包含对象的JSON的长度

angularjs - angular webpack ng-file-upload

java - 如何确保 SFTP session 始终在 spring-batch 结束时关闭