簡體   English   中英

405方法/ gra / spring-security-rest插件在/ api / login OPTIONS請求中不允許(並且戰斗繼續…)

[英]405 Method Not Allowed on /api/login OPTIONS request with grails-spring-security-rest plugin (and the fight continues…)

在我的應用程序中,我使用的是grails-spring-security-rest插件,目前處於構建身份驗證流程的階段。

如果我使用Rest Client,一切都會按預期進行:我可以通過在json中發布用戶名和密碼來登錄並獲取令牌。 完善!

現在,我正在嘗試將整個內容與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
    }

}

攔截器可以完美地獲得有效的get請求,並將標頭添加到響應中。 但是,當我嘗試感覺到這一點時:

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 ,並且執行甚至都沒有進入攔截器。

我的假設是插件提供的登錄控制器不允許這樣做,因此我需要添加一個額外的URL映射來解決此問題。 我的問題是,此映射支持的外觀如何?

另外,可以設置適用於所有OPTIONS請求的映射,因此我不需要一一指定它們嗎?

考慮到所有這些,這只是我的假設……我是否朝着正確的方向邁進?

謝謝,

這個問題也被許多其他用戶所面對,並在github和slack頻道上反復被問到。 我創建了一個示例示例,該示例在src /目錄下具有CORS過濾器,並將其注冊為spring bean。 這是示例應用程序的github回購。 下面是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);
}
}

如下將其作為spring bean注冊到resources.groovy文件中:

beans = {
    corsFilter(CorsFilter)
}

這是此插件的github回購上問的問題。

更新 Grails3 CORS攔截器插件已更新為包括SpringSecurityCorsFilter。 有關如何使用的詳細信息,請參考此示例

這個插件比我上面寫的servlet過濾器好得多。

Shurik,您所說的“過濾器”現在稱為“攔截器”,以匹配更常見的術語。 不建議使用此“過濾器”,因為在Grails / SpringBoot中這是“實際”過濾器。 這就是為什么由於所有命名混亂而使Interceptor不被稱為Interceptor的原因。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM