使用 Grails 3 配置 CORS

Posted

技术标签:

【中文标题】使用 Grails 3 配置 CORS【英文标题】:Configuring CORS with Grails 3 【发布时间】:2017-02-15 06:56:05 【问题描述】:

我正在尝试使用此插件在 Grails 3.1.12 应用程序中启用 CORS 支持:https://github.com/appcela/grails3-cors-interceptor

我遵循了文档,这是我在 application.groovy 中的安全配置:

grails.plugin.springsecurity.controllerAnnotations.staticRules = [
[pattern: '/',               access: ['permitAll']],
[pattern: '/error',          access: ['permitAll']],
[pattern: '/index',          access: ['permitAll']],
[pattern: '/index.gsp',      access: ['permitAll']],
[pattern: '/shutdown',       access: ['permitAll']],
[pattern: '/assets/**',      access: ['permitAll']],
[pattern: '/**/js/**',       access: ['permitAll']],
[pattern: '/**/css/**',      access: ['permitAll']],
[pattern: '/**/images/**',   access: ['permitAll']],
[pattern: '/**/favicon.ico', access: ['permitAll']],
// EDIT: block all other URL access
[pattern: '/**', access: ['denyAll'], httpMethod: 'GET'],
[pattern: '/**', access: ['denyAll'], httpMethod: 'POST'],
[pattern: '/**', access: ['denyAll'], httpMethod: 'PUT'],
[pattern: '/**', access: ['denyAll'], httpMethod: 'DELETE']
]

grails.plugin.springsecurity.filterChain.chainMap = [
[pattern: '/assets/**',      filters: 'none'],
[pattern: '/**/js/**',       filters: 'none'],
[pattern: '/**/css/**',      filters: 'none'],
[pattern: '/**/images/**',   filters: 'none'],
[pattern: '/**/favicon.ico', filters: 'none'],
[pattern: '/api/login',      filters: 'securityCorsFilter,restAuthenticationFilter'],
// see http://alvarosanchez.github.io/grails-angularjs-springsecurity-workshop/
//  [pattern: '/**',             filters: 'JOINED_FILTERS'],
[
    pattern: '/api/**',
    filters: 'JOINED_FILTERS,-anonymousAuthenticationFilter,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter,-rememberMeAuthenticationFilter'
]
]
// EDIT: Optimistic approach (restrict access by URL only) to allow 'OPTIONS' access for CORS
grails.plugin.springsecurity.rejectIfNoRule = false
grails.plugin.springsecurity.fii.rejectPublicInvocations = false

我的问题是,当我向我的任何 /api/something 端点发送一个 OPTIONS 请求而不提供授权标头时,我得到一个 401 状态,我不明白为什么。

【问题讨论】:

您似乎没有按照github.com/appcela/…中提到的所有步骤进行操作 @ÁlvaroSánchez-Mariscal 你是什么意思?我错过了哪一步?我没有在这里展示它,但我还为 OPTIONS 调用添加了一些映射到 UrlMappings (顺便说一下,据说在 Grails 3.1.4+ 中是可选的,但是当我没有这样做时,我得到了 404) .这样,如果我添加带有有效令牌的 Authorization 标头,我会得到 200,但如果没有标头,我会得到 401。 @ÁlvaroSánchez-Mariscal 似乎没有正确激活 CorsInterceptor,即使我将 Angular 2 前端与示例后端连接,所以我在 repo 中为此创建了一个问题:github.com/appcela/… 【参考方案1】:

好的,我注意到与sample project 的一个关键区别。我的项目在控制器级别使用RestfulController@Secured 注释,这就是OPTIONS 401 的原因。我覆盖了所有方法以在方法级别保护它们,现在我不再得到 401。

【讨论】:

【参考方案2】:

您可以尝试这个解决方案(对我有用,使用 grails 3.1.x):

CrosFilter.java:

import org.springframework.web.filter.OncePerRequestFilter;
import javax.annotation.Priority;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Priority(Integer.MIN_VALUE)
public class CorsFilter extends OncePerRequestFilter 

    public CorsFilter()  

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

        String origin = req.getHeader("Origin");

        boolean options = "OPTIONS".equals(req.getMethod());
        if (options) 
            if (origin == null) return;
            resp.addHeader("Access-Control-Allow-Headers", "origin, authorization, accept, content-type, x-requested-with");
            resp.addHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS");
            resp.addHeader("Access-Control-Max-Age", "3600");

        

        resp.addHeader("Access-Control-Allow-Origin", origin == null || origin.equals("null") ? "*" : origin);
        resp.addHeader("Access-Control-Allow-Credentials", "true");

        if (!options) chain.doFilter(req, resp);
    

如果您使用插件配置文件: src/main/groovy/pluginname/PluginNameGrailsPlugin.groovy:

 Closure doWithSpring() 
         ->
            corsFilter(CorsFilter)
         

对于网络应用程序配置文件: grails-app/conf/spring/resources.groovy:

beans = 
corsFilter(CorsFilter)

【讨论】:

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

使用 Grails 3 和 Spring Security REST 配置 CORS

如何在 Grails 3.0.1 中启用 CORS

grails中的CORS - 所有请求都失败了吗?

带有 Spring Security 核心和 CORS 插件的 grails REST API 不适用于 OPTIONS http 方法请求

使用 React 的 AWS CDN 上的 CORS 问题

使用“gradle test”测试 Grails 3 应用程序使用错误的环境配置