spring - 405 Method Not Allowed on/api/login OPTIONS request with grails-spring-security-rest plugin(战斗继续......)

标签 spring rest grails cors

在我的应用程序中,我正在使用 grails-spring-security-rest 插件,目前我正处于构建身份验证流程的阶段。

如果我使用休息客户端,一切都按预期工作:我可以通过在 json 中发布用户名和密码来登录并取回 token 。完美!

现在,我正在尝试将这一切与 Web 表单集成,当然,浏览器会发送预检 OPTIONS 请求。

我有一个简单的拦截器设置:

@GrailsCompileStatic
class CorsInterceptor {
    int order = HIGHEST_PRECEDENCE

    CorsInterceptor() {
        matchAll() // match all controllers
        //.excludes(controller:"login")   // uncomment to add exclusion
    }

    boolean before() {
        String origin = request.getHeader("Origin");

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

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

        true // proceed to controller
    }

    boolean after() { true }

    void afterView() {
        // no-op
    }

}

拦截器完美地获得了有效的获取请求并将 header 添加到响应中。然而,当我试图感知这个时:

curl -X "OPTIONS" "http://localhost:8080/api/login" \
    -H "Origin: http://localhost:3000" \
    -H "Content-Type: application/json" \
    -d "{\"username\":\"customer\",\"password\":\"password\"}"

我总是返回 405 Method Not Allowed 并且执行甚至根本没有到达拦截器。

我的假设是插件提供的登录 Controller 不允许这样做,我需要放置一个额外的 URL 映射来解决这个问题。我的问题是,这个映射支持看起来像什么?

此外,可以设置适用于所有 OPTIONS 请求的映射,因此我不需要一一指定它们?

考虑到所有这些,这只是我的假设……我的方向是否正确?

谢谢,

最佳答案

许多其他用户也遇到了这个问题,并在 github 和 slack channel 上被反复询问。我创建了一个示例示例,它在 src/目录下有 CORS 过滤器,我已经将它注册为 spring bean。 Here is带有示例应用程序的 github repo。 Cors过滤器代码如下

@Priority(Integer.MIN_VALUE)
class CorsFilter extends OncePerRequestFilter {
@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);
    resp.addHeader("Access-Control-Allow-Credentials", "true");

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

在 resources.groovy 文件中将其注册为 spring bean,如下所示:

beans = {
    corsFilter(CorsFilter)
}

Here is这个插件的 github repo 上提出的问题。

更新 Grails3 CORS interceptor plugin已更新为包含 SpringSecurityCorsFilter。使用方法详见this sample

这个插件比我上面写的 servlet 过滤器好得多。

关于spring - 405 Method Not Allowed on/api/login OPTIONS request with grails-spring-security-rest plugin(战斗继续......),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36399403/

相关文章:

rest - 对于损坏的有效负载(校验和失败),最合适的 HTTP 错误代码是什么?

spring - 服务之外的 Grails 依赖注入(inject)?

spring - 如何更改grails中的约束错误消息

grails - 可以用 g :form and g:link in grails 2. x 建立安全的 https 链接吗?

java - Spring DI NullPointerException @Autowired 失败

java - 如何将 HttpServletResponse 响应获取到 Spring Boot 的 REST Controller 中?

java - Spring 示例,其中值未硬编码在 XML 配置文件中

java - Spring Maven - 无法生成 WSDL

java - Android 设备针对 Spring Security Rest API 的身份验证

rest - Linkedin REST API 检索用户的状态更新