angular2 spring boot 跨域 cors

Posted

技术标签:

【中文标题】angular2 spring boot 跨域 cors【英文标题】:angular2 spring boot cross-origin cors 【发布时间】:2017-05-11 01:36:19 【问题描述】:

我的项目遇到了跨源 cors 问题。我必须从在 localhost:4200 上运行的 Angular2 应用程序向我在 localhost:8080 上运行的 Spring Boot 后端发送一个获取请求,并带有一些标头属性。我要发送的请求如下所示:

test() 
  let jwt = localStorage.getItem('token');
  let headers = new Headers(
        'Content-Type': 'application/json; charset=utf-8',
        'Authorization': 'Bearer ' + jwt 
    );

    let options = new RequestOptions( headers: headers );
    this.http.get('http://localhost:8080/service/events/byTeamId/1', options)
        .map((response: Response) => response.json())
        .subscribe(
            data => console.log('Response: '+data),
            err => console.log('error: '+err),
            () => console.log('Secret Quote Complete')
        );



但是这个请求并没有到达服务器端,我想得到它。使用 Postman 测试它的工作原理。

我的 Spring Boot 后端如下所示:

WebSecurityConfig.java:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 

    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    @Autowired
private SimpleCorsFilter simpleCorsFilter;

@Resource
private UserDetailsServiceImpl userDetailsService;

@Resource
private JwtAuthenticationProvider jwtAuthenticationProvider;

@Override
protected void configure(HttpSecurity http) throws Exception 
    http
            .authorizeRequests()
                .antMatchers("/", "/home", "/login", "/register").permitAll()
                .anyRequest().authenticated()
                .and()
            .addFilterBefore(simpleCorsFilter, ChannelProcessingFilter.class)
            .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
            .logout()
                .permitAll()
            .and().csrf().disable();

...

我的 SimpleCorsFilter 如下所示:

    @Component
public class SimpleCorsFilter implements Filter 

    private final Logger log = LoggerFactory.getLogger(SimpleCorsFilter.class);

    public SimpleCorsFilter() 
        log.info("SimpleCORSFilter init");
    

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException 

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "http://localhost:4200");
        //response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me, Authorization");

        chain.doFilter(req, res);
    

    @Override
    public void init(FilterConfig filterConfig) 
    

    @Override
    public void destroy() 
    


使用邮递员它可以正常工作:

Postman Get Request

但是当我在我的 chrome 浏览器上测试它时,我得到:

Chrome Request

所以对我来说,我的后端似乎没有收到像“授权”这样的标题属性。我也通过在 Spring Boot 后端调试请求来看到这一点。我只是将“null”视为此请求的标头。

有人知道为什么我的请求标头在 api 端点上没有正确吗?

我已经看过这里了:

restlet.com/blog/2016/09/27/how-to-fix-cors-problems/

并查看了 *** 上发布的几个类似问题。

【问题讨论】:

你试过把"Access-Control-Allow-Origin", "http://localhost:4200"改成"Access-Control-Allow-Origin", "*" 它适用于这个解决方案:将它添加到 spring 安全配置中:.antMatchers(org.springframework.http.HttpMethod.OPTIONS, "/service/**").permitAll() ***.com/questions/36142155/… 蚂蚁感谢您的意见。是的,我也尝试过 ` "Access-Control-Allow-Origin", "*" ` 太棒了,你想通了! :) 让我们提出你的答案,你应得的:D 【参考方案1】:

对我来说,它适用于这个解决方案: 将此添加到 Spring 安全配置中:

.antMatchers(org.springframework.http.HttpMethod.OPTIONS, "/service/**").permitAll()

http
.authorizeRequests()
                .antMatchers("/", "/home", "/login", "/register").permitAll()
                .antMatchers(org.springframework.http.HttpMethod.OPTIONS, "/service/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .addFilterBefore(simpleCorsFilter, ChannelProcessingFilter.class)
            .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
            .logout()
                .permitAll()
            .and().csrf().disable();

(jwt token 还是需要的,我想怎么弄)

来自:

CORS Origin Spring Boot Jhipster - pre-flight fails

【讨论】:

腰围 4 小时认为我的标题不正确。即使在启用 CROS 后也没有任何效果。 .antMatchers(org.springframework.http.HttpMethod.OPTIONS, "/service/**") 有效,但是为什么即使我们已经设置了这仍然需要 JWT 身份验证。 permitALL()?【参考方案2】:

我遇到了同样的问题,我正在为我的 api 和 Angular 2.3.1 使用 spring boot。我不确定您是否使用 Npm 和 Angular Cli。如果您使用 npm 进行开发,则可以执行以下操作来解决此问题。您可以将 api 调用代理到您的后端。

第一步:在 package.json 的同一目录下创建一个名为 proxy.conf.json 的文件,内容如下


  "/api": 
    "target": "http://localhost:8080",
    "secure": false,
    "pathRewrite": "^/api" : ""
  

因此,您将使用/api/service/events/byTeamId/1,而不是使用http://localhost:8080/service/events/byTeamId/1 来处理您的api 请求

注意添加的“/api”和删除的“http://localhost:8080”。这意味着任何以 /api 开头的请求都将被代理。这就是您想要的,因为您不只是希望任何 url 被代理。线 "pathRewrite": "^/api" : "" 确保删除“/api”,以便最终请求您的实际网址。

第 2 步:更新 package.json

更新行 "start": "ng serve", 并将其更改为 "start": "ng serve --proxy-config proxy.conf.json", 这将确保代理已配置和使用

第 3 步:使用 npm start

在使用 Angular cli 并确保您位于项目目录中时,您现在可以启动您的应用程序,您的请求被使用代理

npm start

Angular Cli documentation

【讨论】:

以上是关于angular2 spring boot 跨域 cors的主要内容,如果未能解决你的问题,请参考以下文章

angular2 spring-boot项目结构

带有 Spring Boot 和 Spring Security 的 Angular2

Angular2 Spring Boot JWT 缺少响应标头

Angular2 和 Spring Boot。如何服务前端?

同一台服务器上的 Spring Boot + Angular2

跨域不适用于 Spring Boot