[英]Spring boot CORS Filter not working with AngularJS
我创建了一个SpringBoot应用程序,它有一个AngularJS前端,我没有使用任何Spring Security模块。
我在控制器中添加了@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
具有开箱即用的安全性。 这里的问题是它们在根上下文中应用安全性,这意味着任何其他端点也将具有身份验证。
要解决此问题,您可以创建自己的具有更高优先级的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();
}
}
或者,您可以禁用Activiti的安全自动配置:
@EnableAutoConfiguration(exclude = {
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration.class,
org.activiti.spring.boot.SecurityAutoConfiguration.class
})
这将禁用Activiti和Spring启动本身的安全自动配置。 如果您只是禁用Activiti的安全配置,Spring boot的自动配置将启动,您仍然可以在所有端点上进行身份验证。
但是,您可能仍希望在某些Activiti的端点上应用安全性,但这允许您自己进行自定义,而不是依赖于自动配置。 在您的情况下,您可以选择将安全性应用于所有/identity/**
, /management/**
, /history/**
, /repository/**
, /query/**
和/runtime/**
路径,正在被Activiti使用。
OPTIONS
情况下覆盖过滤器链 第三种选择是绕过整个安全过滤链。 如本回答所示,您可以通过不调用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
}
注意 :请注意,这只会允许
OPTIONS
调用通过。 安全性还会影响您在控制器中定义的其他端点,而不仅仅是OPTIONS
调用。
通过有条件地调用doFilter()
,您可以跳过整个安全过滤器链,以防OPTIONS
请求进入。您必须分别将req
和res
为HttpServletRequest
和HttpServletResponse
。
此外,您必须确保在安全过滤器链之前调用此过滤器。 为此,请将CORSFilter
的顺序更改为所选值,例如:
@Component
@Order(1) // You can choose the value yourself
public class CORSFilter implements Filter {
// ...
}
现在通过将application.properties
的security.filter-order
属性设置为更高的值来更改安全筛选器链顺序:
security.filter-order=2
这是一个Spring CORS过滤器,可以与AngularJS一起使用
public class CORSFilter extends OncePerRequestFilter {
private final Logger LOG = LoggerFactory.getLogger(CORSFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws ServletException, IOException {
LOG.info("Adding CORS Headers ........................");
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
res.setHeader("Access-Control-Max-Age", "3600");
res.setHeader("Access-Control-Allow-Headers", "X-PINGOTHER,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization");
res.addHeader("Access-Control-Expose-Headers", "xsrf-token");
if ("OPTIONS".equals(req.getMethod())) {
res.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
我发现这个帖子来自Spring Cors允许所有的起源
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.