Wildfly 为所有预检请求返回 405

Wildfly returns 405 for all preflight requests

提问人:georgebax 提问时间:11/2/2023 最后编辑:georgebax 更新时间:11/3/2023 访问量:36

问:

我在 Widfly (27.0.1) 上部署了一个 Web 应用程序,以及一个尝试在此应用程序中调用 REST 端点的 VueJS 客户端。因为我收到这个错误(,所以我按照指南在启动时使用 .cli 脚本将 CORS 添加到 wildfly 配置中。请注意,这是一个 GET 请求,但我认为由于 Content-Type,它被认为是“复杂的”。Access to XMLHttpRequest at 'http://localhost:8899/my-services/rest-api/selection-data/all' from origin 'http://127.0.0.1:5173' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.application/json

但是,这并没有解决任何问题,即使我现在在CORS预检请求的响应中获得了这些标头:

Access-Control-Allow-Credentials:
true
Access-Control-Allow-Headers:
accept, authorization, content-type, x-requested-with
Access-Control-Allow-Methods:
GET, POST, OPTIONS, PUT
Access-Control-Allow-Origin:
*
Access-Control-Max-Age:
1
...

我还尝试创建一个 resteasy 并将其添加到应用程序中,我可以看到它是在部署时添加的,但其中没有调用任何内容。我创建的注释也是如此,它创建了一个 ,尽管我不确定这个是否被 Wildfly 选中。org.jboss.resteasy.plugins.interceptors.CORSFilter@ProviderFeatureCORSFilter

在阅读了更多内容后,我发现 servlet 过滤可能在 CORS 过滤器可以执行任何操作之前发生,因为 servlet 级别先于 JAX-RS 级别。但此时此刻,我不知道该怎么办。我有一个 servlet 过滤器类,如下所示:

@WebFilter(urlPatterns = { "/*" })
public class UserCredentialFilter implements Filter {

    private static final Logger LOGGER = LoggerFactory.getLogger(UserCredentialFilter.class);

    private final User user;

    @Inject
    public UserCredentialFilter(User user) {
        this.user = user;
    }

    @Override
    public void init(FilterConfig filterConfig) {
        // nothing to do
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        HttpServletRequest httpServletRequest = ((HttpServletRequest) servletRequest);
        // it doesn't enter this point in preflight requests
        if (httpServletRequest.getMethod().equalsIgnoreCase("OPTIONS")) {
            // below doesn't get called either
            System.out.println("In a preflight request?");
            return;
        }

        Principal userPrincipal = httpServletRequest.getUserPrincipal();
        if (userPrincipal != null) {
            ///// user-related logic
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
        // nothing to do
    }
}

我应该在什么时候处理此印前检查请求?谁和代码的哪一部分返回不允许使用 OPTIONS 方法?

编辑:我刚刚发现,如果 Access-Control-Allow-Credentials 也设置为 true,则无法使用 ACAO 标头中的通配符 (*),但我认为不会返回 405 代码,根据规范,它将是“原因:如果 CORS 标头”Access-Control-Allow-Origin“为”*“,则不支持凭据 "

java servlet cors jax-rs wildfly

评论

0赞 James R. Perkins 11/2/2023
你是这样注册过滤器的吗?docs.jboss.org/resteasy/docs/6.2.5.Final/userguide/html/......
0赞 georgebax 11/3/2023
嗨,@JamesR.Perkins,我在执行此操作时将通配符添加到了原点。在了解有关 CORS 的更多信息后,我认为它不允许与 AC-Allow-Credentials 标头一起使用。无论如何,我将使用最终实施的修复程序来回答我的问题。

答:

0赞 georgebax 11/3/2023 #1

显然,当 Postman 在没有先登录的情况下发送 OPTION 请求时,问题也出现了(我们有一个返回身份验证令牌的端点),但是登录后,OPTION 请求就可以正常工作 - 所以这实际上是一个授权问题,隐藏在这个 405 方法后面不允许”。解决方法是最终将此行添加到 web.xml,它绕过了 OPTION 请求的授权机制:

    <security-constraint>
        <display-name>SecurityConstraint</display-name>
        <web-resource-collection>
            <web-resource-name>Secured page</web-resource-name>
            <url-pattern>/rest-api/*</url-pattern>
            <http-method-omission>OPTIONS</http-method-omission> // this one
        </web-resource-collection>
        ...
    </security-constraint>

但这本身是不够的,因为 Wildfly 不会返回所需的 CORS 标头,因此还需要根据配置 wildfly 映像,并修改 Access-Control-Allowed-Origin 标头返回域名而不是通配符。