使用 Grails 3 和 Spring Security REST 配置 CORS

Posted

技术标签:

【中文标题】使用 Grails 3 和 Spring Security REST 配置 CORS【英文标题】:Configuring CORS with Grails 3 and Spring Security REST 【发布时间】:2017-02-16 04:03:06 【问题描述】:

我正在尝试弄清楚如何将 Angular 2 前端(在 localhost:4200 上运行)插入 Grails 3 后端(在 localhost:8080 上运行),因此我需要在 grails 应用程序中启用 CORS 支持。

我发现了这个 Github 项目 (https://github.com/appcela/grails3-cors-interceptor-spring-security-rest-sample-app),它展示了如何使用 grails3-cors-interceptor 插件启用 CORS。我正在运行这个应用程序作为测试后端,我在CorsService.processPreflight() 中放置了一个断点来检查它何时被调用。当我在/api/books 上执行 GET 时,浏览器首先发送一个通过断点的 OPTIONS 调用,但是下面的 GET 似乎没有到达那里,我不知道为什么。有什么想法吗?

【问题讨论】:

嘿! Grails 3.2.1 刚刚发布。它内置了 CORS docs.grails.org/latest/guide/introduction.html#whatsNewCors 【参考方案1】:

更新

Grails 3.2.1 具有支持 CORS 的内置功能。看看这个http://docs.grails.org/latest/guide/theWebLayer.html#cors

只需将其添加到您的 application.yml 即可启用它

grails:
    cors:
        enabled: true

(确保查找要启用 CORS 的环境)

原帖

您不需要插件(除非您想使用该插件)在此处启用 CORS。好吧,对于您的其余端点,您始终可以使用 Grails 拦截器启用 CORS,如下所示:

class CorsInterceptor 

    CorsInterceptor() 
        matchAll()
    

    boolean before() 
        if (request.method == "OPTIONS") 
            response.setHeader("Access-Control-Allow-Origin", "http://localhost:4200")
            response.setHeader("Access-Control-Allow-Credentials", "true")
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE")
            response.setHeader("Access-Control-Max-Age", "3600")

            response.status = 200
        

        return true
    

    boolean after()  true 

但是 Grails 拦截器无法拦截 Spring Security core/rest 插件提供的端点,因为它们的拦截器的优先级高于 Grails 拦截器。所以首先需要添加一个客户过滤器,然后在Spring相关过滤器之前注册。

src/main/groovy中添加一个文件:

package test

import org.springframework.web.filter.OncePerRequestFilter

import javax.servlet.FilterChain
import javax.servlet.ServletException
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

class CorsFilter extends OncePerRequestFilter 

    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse resp, FilterChain chain)
            throws ServletException, IOException 

        if (req.getMethod() == "OPTIONS") 
            resp.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
            resp.addHeader("Access-Control-Max-Age", "3600")
            resp.addHeader("Access-Control-Allow-Origin", "http://localhost:4200")
            resp.addHeader("Access-Control-Allow-Credentials", "true")
            resp.status = 200
         else 
            chain.doFilter(req, resp)
        
    

resources.groovy注册:

beans = 
    corsFilterFoo(CorsFilter)

现在,将它添加到 Spring 的过滤器链中,在安全上下文过滤器之前(在 Bootstrap.groovy 中):

SpringSecurityUtils.clientRegisterFilter("corsFilterFoo",
    SecurityFilterPosition.SECURITY_CONTEXT_FILTER.order - 1)

参考:https://github.com/grails-plugins/grails-spring-security-core/blob/v3.1.1/src/main/groovy/grails/plugin/springsecurity/SpringSecurityUtils.groovy#L698

【讨论】:

在哪里添加最后一行注册过滤器? 糟糕!对不起。添加到Bootstrap.groovy @ShashankAgrawal 我正在使用 Grails 3.2.7 我按照在 application.yml 中使用 grails 3 启用 CORS 的步骤。我试图允许 OPTIONS 方法与任何请求方法一起传递。但是通过简单地启用 cors,我无法实现它。你能详细说明一下吗? 您不必允许 OPTIONS 方法,因为这是用于飞行前请求检查是否允许 CORS 的方法【参考方案2】:

使用最新版本的 Grails 3,如果您在本地运行应用程序,您只需启用 CORS grails run-app。我的版本是Grails Version: 3.3.10。 时髦的grails.cors.enabled=true

【讨论】:

以上是关于使用 Grails 3 和 Spring Security REST 配置 CORS的主要内容,如果未能解决你的问题,请参考以下文章

grails acegi 迁移到 spring-security-core

Grails 3.0 和 Spring Security

使用 Grails 3 和 Spring Security REST 配置 CORS

如何使用 grails 1.3.2 和插件 spring-security-core 1 实现自定义 FilterSecurityInterceptor?

为啥我无法使用 grails 框架 1.3.7 中安装的 spring security 和 weceem 插件登录

Grails 3 和 Spring Security:当用户未登录时返回 401