当前位置: 首页 > 知识库问答 >
问题:

在WebLogic上设置默认CookieManager无效

慕云
2023-03-14

我正在使用Spring的WebServiceGatewaySupport连接到供应商的SOAP Web服务。该服务的要求之一是客户端必须维护服务器发送的会话cookie。

我能够确定WebServiceGatewaySupport在内部使用HttpURLConnection类发出请求。只需呼叫

CookieHandler.setDefault(new CookieManager());

在派对开始之前,添加了一个默认的cookie管理器,一切都非常好地运行在我本地的Tomcat实例上(我甚至注意到我的机器旁边出现了一个小彩虹)。

但是,当我部署到WebLogic 10.3.6.0时,一切都进展顺利。它不像以前那样叽叽喳喳了,我的饼干被扔了。

我能够通过覆盖CookieManager的get和put方法来证明WebLogic是罪魁祸首。Tomcat中对此有很多操作。WebLogic没有杂音。

    CookieHandler.setDefault(new CookieManager() {
        @Override
        public Map<String, List<String>> get(URI uri, Map<String, List<String>> stringListMap) throws IOException {
            Map<String, List<String>> map =  super.get(uri, stringListMap);
            LOGGER.info("Cop that: " + uri + " " + map);
            return map;
        }

        @Override
        public void put(URI uri, Map<String, List<String>> stringListMap) throws IOException {
            LOGGER.info("Hello sailor: " + uri + " " + stringListMap);
            super.put(uri, stringListMap);
        }
    });
    ((CookieManager)CookieHandler.getDefault()).setCookiePolicy(CookiePolicy.ACCEPT_ALL);

我只能假设存在某种“高级安全骗局”,用于传入servlet请求,但也应用于传出连接。我找不到任何有用的weblogic部署描述符选项。

混蛋。

我也许能让它和安讯士一起工作,但我宁愿用钢笔刺自己的脸。

我要回家了。

更新:好的,我还没有解决根本原因,但这就是我工作的方式。我在想,如果我可以访问实际的HttpURLConnection对象,我可以对其进行手动cookie管理。我能够查看Spring WS源代码并设置一个新的MessageSender,其工作原理基本相同。

public class MyClient extends WebServiceGatewaySupport {
    public MyClient(WebServiceMessageFactory messageFactory) {
        super(messageFactory);

        super.getWebServiceTemplate().setMessageSender(new WebServiceMessageSender() {
            @Override
            public WebServiceConnection createConnection(URI uri) throws IOException {
                URL url = uri.toURL();
                URLConnection connection = url.openConnection();
                if (!(connection instanceof HttpURLConnection)) {
                    throw new HttpTransportException("URI [" + uri + "] is not an HTTP URL");
                }
                HttpURLConnection httpURLConnection = (HttpURLConnection) connection;
                prepareConnection(httpURLConnection);

                HttpURLConnectionProxy httpURLConnectionProxy = new HttpURLConnectionProxy(url);
                httpURLConnectionProxy.setHttpURLConnection(httpURLConnection);
                httpURLConnectionProxy.setCookieManager(cookieManager);
                return new MyHttpUrlConnection(httpURLConnectionProxy);
            }

            protected void prepareConnection(HttpURLConnection connection) throws IOException {
                connection.setRequestMethod(HttpTransportConstants.METHOD_POST);
                connection.setUseCaches(false);
                connection.setDoInput(true);
                connection.setDoOutput(true);
                // ORRRRR YEAAHHHHHHH!
                cookieManager.setCookies(connection);
            }

            @Override
            public boolean supports(URI uri) {
                return true;
            }
        });
    }

另一个复杂的问题是,我需要在调用connect()之前和之后设置和获取cookie数据。所以我创建了一个HttpURLConnectionProxy类,它将所有方法调用代理给url生成的方法调用。openConnection()但在connect()之后执行cookie操作;

public void connect() throws IOException {
    httpURLConnection.connect();
    // WOOPWOOPWOOPWOOP!
    cookieManager.storeCookies(httpURLConnection);
}

但这很糟糕

共有1个答案

羿博延
2023-03-14

我认为您正在扭曲CookieManager API的预期用途。请参考文档和CookieManager文档。供应商的要求是维护服务器发送的会话cookie。要达到这一要求,您需要两个步骤:

  1. 在Spring容器中,连接一个Springbean,它保存方法调用CookieHandler。setDefault(新建CookieManager())

假设您使用的是Spring 3.1或更高版本,请在下面找到您的配置类:

@Configuration
@EnableWebMvc   // this annotation imports the class  WebMvcConfigurationSupport which bootstraps web mvc
@ComponentScan(basePackages = { "com.orgname"  })
public class WebConfig extends WebMvcConfigurerAdapter {

@Bean
public ViewResolver viewResolver() {

    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
    viewResolver.setViewClass(JstlView.class);
    viewResolver.setPrefix("/view/jsp/");
    viewResolver.setSuffix(".jsp");
    return viewResolver;
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}

/**
 * This method invocation bean stands for the method call:
 * CookieHandler.setDefault(new CookieManager());
 * which should be done at the beginning of an HTTP session to bootstrap
 * the Java 6 Http state management mechanism for the application as a whole. 
 * (http://docs.oracle.com/javase/tutorial/networking/cookies/cookiehandler.html)
 * 
 */
@Bean(name="cookieHandlerSetDefaultBean") 
public MethodInvokingFactoryBean methodInvokingFactoryBean() { 
    MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
    methodInvokingFactoryBean.setTargetClass(CookieHandler.class);
    methodInvokingFactoryBean.setTargetMethod("setDefault");
    CookieManager cookieManager = new CookieManager();
    methodInvokingFactoryBean.setArguments(new Object[]{cookieManager}); 
    return methodInvokingFactoryBean; 
}
}

假设您的客户机类是Spring服务或组件。请查看下面的代码。

/**
 * This service aggregates the default CookieManager as explained in the API 
 * (http://docs.oracle.com/javase/6/docs/api/java/net/CookieManager.html). 
 * A system-wide CookieManager that is used by the HTTP protocol handler 
 * can be retrieved by calling CookieHandler.getDefault(). 
 * A CookieManager is initialized with aآ CookieStoreآ which manages storage
 * A CookieStore supports add(cookie) and getCookie() methods
 * A CookieStore is responsible of removing Cookie instances which have expired.
 *
 */
@Service(value="serviceConfigBean")
@DependsOn(value="cookieHandlerSetDefault")    //This is the bean initialized in the Configuration class. It is needed to be initialized before the container initializes the Service 
public class ClientCookiesStore {

    private static final Logger logger = LoggerFactory.getLogger(ClientCookiesStore.class);

    protected CookieStore inmemoryCookieStore;

    protected URI clientURI;

/**
 * The @PostConstruct (lifecycle callback method) indicates this method should be invoked after all 
 * dependency injection is complete. Thus helps in initializing any resources needed by the 
 * service.
 * 
 * In this particular initializing method:
 * (as per http://docs.oracle.com/javase/6/docs/api/java/net/CookieManager.html
 *  and http://docs.oracle.com/javase/tutorial/networking/cookies/cookiemanager.html)
 * The CookieHandler default is installed in the application via 
 * a method invoking factory bean, namely "cookieHandlerSetDefault" which 
 * exists in the java configuration file WebConfig.java

 * (1) A cookieManager property needs 2 steps setup as indicated in the code
 * (2) The internal in-memory implementation of the CookieStore interface is initialized 
 *      through the cookieManager defaults. It is assigned to the inmemoryCookieStore property.  
 * (3) Since a CookieStore aggregates many groups of cookies, each group is identified 
 *     by a URI instance. ClientCookiesStore is associated with the Client URI as indicated in 
 *     the code.  
 * 
 * @throws Exception
 */
@PostConstruct
protected void initializeBean() throws Exception {
    //      (1) Step#1 Initialize a CookieManager with the current Http session default 
    //                  which was already set in the configuration class
    CookieManager cookieManager = (CookieManager)CookieHandler.getDefault();    
    //          Step#2 Then set up the CookiePolicy.
    cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
    //      (2) Assign a CookieStore instance to the in-memory cookie store implemented by the API
    inmemoryCookieStore =  cookieManager.getCookieStore();
    //      (3) Initialize URI instance which will identify the Client cookies in the CookieStore 

    try {
        clientURI = new URI("http://vendor.webservices.com/endpoint");
    } catch (URISyntaxException e) {
        throw new Exception("URISyntaxException created while creating a URI instance for url= "+clientUrl);
    }
}

}

剩下的就是添加新cookie和从内存存储中检索cookie的2种方法。这两种方法都属于上面的ClientCookiesStore类。

public List<HttpCookie> getCookiesList() throws Exception {
    List<HttpCookie> httpCookiesList = inmemoryCookieStore.get(clientURI);
    return httpCookiesList;
}

public void addCookie(HttpCookie newCookie) {
        inmemoryCookieStore.add(clientURI, newCookie);
}
 类似资料:
  • 我有一个Java应用程序,我使用了Hibernate、Primefaces、JSF、Jquery、Twitterbootstrap和Spring。 我的应用程序中有许多数据表。 我希望DataTable有一个默认的选定项。 primefaces提供了什么方法吗?以下是它现在的样子: 以下是DataTable:

  • 问题内容: 有没有一种方法可以在共享首选项中设置默认值? 这是我的负载偏好代码 这是我的保存偏好代码 问题答案: 当您使用键和值设置首选项时,实际上是在提供该值。因此,这次不必使用默认值。请参见,在检索该值时,如果以前未设置该值,则可以定义一个默认值。 如果您得到strSavedMem1 =“ default”,那么肯定是默认情况,因为您没有在首选项中为MEM1设置任何其他值

  • 问题内容: 我正在尝试向每个API调用添加带有访问令牌的标头。它适用于所有GET请求,但是一旦我尝试进行POST,便不会添加标头。 这是我添加令牌的方法: 从这里调用: 我尝试这样做如下: 但这也不起作用。它仅在我如下更改标题键名称时才有效: 如何在AngularJs中为帖子分配默认标题并获取请求? 问题答案: 与其将令牌放在每个服务(或调用)内部的标头上,不如使用拦截器(docs在此处)。 然后

  • 我在Windows 10上使用的是VSCode 1.47.3。我无法编辑json中的默认设置: 打开默认设置(“文件 - 我尝试过以管理员身份打开VSCode,卸载并重新安装,重新启动计算机,并将其降级到1.46,但仍然无法编辑。有人知道如何解决这个问题吗?

  • 什么是Locale Locale是一组描述世界上某一特定区域文本格式和语言习惯的设置的集合。locale名通常由三个部分组成:第一部分,是一个强制性的,表示语言的缩写,例如"en"表示英文或"zh"表示中文。第二部分,跟在一个下划线之后,是一个可选的国家说明符,用于区分讲同一种语言的不同国家,例如"en_US"表示美国英语,而"en_UK"表示英国英语。最后一部分,跟在一个句点之后,是可选的字符集

  • 问题内容: 我要在这里做的是 使python3成为默认的python。 除了在Mac上自动安装的python 2.7之外,我还使用 homebrew 安装了 python3 。这是我关注的网站。http://docs.python-guide.org/zh- CN/latest/starting/install3/osx/#install3-osx 我想我很好地遵循了每条指令,重新安装了xcode