GET 请求被禁止,而 POST 请求正常

问题描述 投票:0回答:2

在我的 web 应用程序中,我需要调用不同的 web 服务(由我开发/管理)以通过 rest API 启动/管理资源。 Web 服务运行在 tomcat6 上。我可以从浏览器日志中看到 POST 请求正在通过,但 GET 请求被禁止。如果我从 Web 服务本身进行相同的调用,那么我看不到任何问题。我已经为 tomcat6 定义了跨源过滤器,并在支持的方法中也提到了 GET 但问题仍然存在..

我已经在应用程序服务器级别本身的 web.xml 中以这种方式定义了跨源过滤器。我正在使用来自 http://software.dzhuvinov.com/cors-filter.html 的 CORS 过滤器库。这是一个 tomcat6 服务器,过滤器已在 ($TOMCAT6_HOME/conf/web.xml) 中定义如下

<filter>
    <filter-name>CORS</filter-name>
    <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
    <init-param>
     <param-name>cors.allowOrigin</param-name>
        <param-value>*</param-value>
    </init-param>
    <init-param>
     <param-name>cors.supportedMethods</param-name>
        <param-value>GET, POST, HEAD, PUT, DELETE, OPTIONS</param-value>
    </init-param>
    <init-param>
     <param-name>cors.supportedHeaders</param-name>
     <param-value>*</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>CORS</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

奇怪的是,webservice 正在接受 POST 调用,但对于 GET 调用,它会抛出 403 - Forbidden 错误,告知“已禁止访问指定资源”。

GET 调用的标头如下

Request URL:https://remote.vm.mycompany.com/remote/tunnel?read:c2faeb31-4147-49e8-b8d3-53d89496e5ca:0
Request Method:GET
Status Code:403 Forbidden
Request Headersview source
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Host:remote.vm.mycompany.com
Origin:https://ec2-184-72-200-91.compute-1.amazonaws.com
Referer:https://ec2-184-72-200-91.compute-1.amazonaws.com/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36
Query String Parametersview sourceview URL encoded
read:c2faeb31-4147-49e8-b8d3-53d89496e5ca:0:
Response Headersview source
Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin:https://ec2-184-72-200-91.compute-1.amazonaws.com
Content-Length:961
Content-Type:text/html;charset=utf-8
Date:Sun, 21 Jul 2013 17:17:37 GMT
Server:Apache-Coyote/1.1

Tomcat 访问日志也显示 GET 请求已被禁止,但没有在任何日志中提供任何线索

- - - [21/Jul/2013:17:17:37 +0000] POST /remote/tunnel?connect HTTP/1.1 200   -
- - - [21/Jul/2013:17:17:37 +0000] GET /remote/tunnel?read:c2faeb31-4147-49e8-b8d3-53d89496e5ca:0 HTTP/1.1 403   -

这是我的 servlet 代码。我正在尝试集成 guacamole(HTML5 VNC 客户端作为 web 服务)

package com.mycompany.html5remote;

import java.util.Arrays;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.sourceforge.guacamole.GuacamoleException;
import net.sourceforge.guacamole.net.GuacamoleSocket;
import net.sourceforge.guacamole.net.GuacamoleTunnel;
import net.sourceforge.guacamole.net.InetGuacamoleSocket;
import net.sourceforge.guacamole.protocol.ConfiguredGuacamoleSocket;
import net.sourceforge.guacamole.protocol.GuacamoleClientInformation;
import net.sourceforge.guacamole.protocol.GuacamoleConfiguration;
import net.sourceforge.guacamole.servlet.GuacamoleHTTPTunnelServlet;
import net.sourceforge.guacamole.servlet.GuacamoleSession;

public class HttpTunnel extends GuacamoleHTTPTunnelServlet {

    private Logger logger = LoggerFactory.getLogger(HttpTunnel.class);

    @Override
    protected GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException {

        HttpSession httpSession = request.getSession(true);
        logger.info("Inside doConnect Method.");


        GuacamoleClientInformation info = new GuacamoleClientInformation();

        String hostname = request.getParameter("hostname");
        String protocol = request.getParameter("protocol");

        // Create socket
        GuacamoleConfiguration config = new GuacamoleConfiguration();
        config.setProtocol(protocol);
        config.setParameter("hostname", hostname);
        //config.setParameter("hostname", "ec2-184-73-104-108.compute-1.amazonaws.com");
        if("vnc".equals(protocol)){
            config.setParameter("port", "5901");
        }else if ("rdp".equals(protocol)){
            config.setParameter("port", "3389");
        }else{
            config.setParameter("port", "22");
        }

        logger.info("Set the configuration. Creating the socket connection now..");

        // Return connected socket
        GuacamoleSocket socket =  new ConfiguredGuacamoleSocket(
                new InetGuacamoleSocket("localhost", 4822),
                config, info
        );

        logger.info("Successfully created socket connection.");


        // Create tunnel from now-configured socket
        GuacamoleTunnel tunnel = new GuacamoleTunnel(socket);

        // Attach tunnel
        GuacamoleSession session = new GuacamoleSession(httpSession);
        session.attachTunnel(tunnel);
        logger.info("Done");
        return tunnel;

    }

}

GuacamoleHTTPTunnelServlet(GPL 许可)的文档在这里

我可能错过了什么?还有其他地方我可以寻找线索吗?请帮助

java rest cross-domain html5-canvas tomcat6
2个回答
0
投票

您是否有任何与 web.xml 中配置的 http 方法相关的安全约束?我不确定你为什么要使用单独的 api 来过滤你的请求?


0
投票

我花了几天时间尝试将我的 Spring Boot 与 Apache Guacamole 后端连接到我的 NextJS 前端,这是对我有用的解决方案(参考 StackOverflow 上的这个issue):

问题有两个主要部分,CORS 和 CSRF。首先,创建一个新的 Java 类并设置一个 CORS 配置,其中包含 Guacamole 需要的标头和方法,以及前端服务器的来源。这确保了 Spring Boot 服务器将使用正确的 CORS 标头响应来自前端的请求,这样它就不会被浏览器阻止。

@Bean
CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
    configuration.setAllowedMethods(Arrays.asList("*"));
    configuration.setAllowedHeaders(Arrays.asList("*"));
    configuration.setAllowCredentials(true);
    configuration.setExposedHeaders(Arrays.asList("Guacamole-Status-Code", "Guacamole-Error-Message", "Guacamole-Tunnel-Token"));
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;
}

其次,通过适当的 CORS 配置,将允许以“/tunnel?connect”结尾的 POST 请求,但仍将阻止以“/tunnel?read:some-numbers-and-text:0”结尾的后续 GET 请求.这就是 CSRF 发挥作用的地方,因为请求可能由于 Spring Security 的默认 CSRF 保护而被拒绝。因此,只需创建一个新的 SecurityFilterChain 并指定行“http.cors().and().csrf().disable();”即可禁用 CSRF(您可以稍后配置)。然后将接受 POST 请求,并可以启动 Apache Guacamole 隧道。

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

    // Adds a CorsFilter to be used. If a bean by the name of corsFilter is provided, that CorsFilter is used. 
    // Else if corsConfigurationSource is defined, then that CorsConfiguration is used.
    http.cors().and().csrf().disable();

    return http.build();
}

这是完整的 Java 类:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        // Adds a CorsFilter to be used. If a bean by the name of corsFilter is provided, that CorsFilter is used. 
        // Else if corsConfigurationSource is defined, then that CorsConfiguration is used.
        http.cors().and().csrf().disable();

        return http.build();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
        configuration.setAllowedMethods(Arrays.asList("*"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setAllowCredentials(true);
        configuration.setExposedHeaders(Arrays.asList("Guacamole-Status-Code", "Guacamole-Error-Message", "Guacamole-Tunnel-Token"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.