Jersey 客户端 API 中的 Content-MD5

发布于 2024-11-14 23:48:57 字数 1167 浏览 0 评论 0原文

我正在尝试在使用 Jersey Client API 创建的请求上设置 Content-MD5 标头。我创建了 ClientFilter,它实现了另一个适配器(类似于 GZipFilter 的工作方式)。像这样:

public class ContentMD5Filter extends ClientFilter {

    private static final class ContentMD5Adapter extends AbstractClientRequestAdapter {
        ContentMD5Adapter(final ClientRequestAdapter cra) {
            super(cra);
        }

        @Override
        public OutputStream adapt(final ClientRequest request, final OutputStream out) throws IOException {
            try {
                MessageDigest instance = MessageDigest.getInstance("MD5");
                request.getHeaders().add("Content-MD5", instance);
                return new DigestOutputStream(out, instance);
            } catch (NoSuchAlgorithmException e) {
                throw new WebApplicationException();
            }
        }
    }

    @Override
    public ClientResponse handle(final ClientRequest cr) throws ClientHandlerException {
        cr.setAdapter(new ContentMD5Adapter(cr.getAdapter()));
        return getNext().handle(cr);
    }
}

这不起作用,因为摘要被提前读取(即在写入整个内容之前)。

关于如何做到这一点有什么想法吗?除了设置标题之外,我还需要在之后在另一个过滤器中访问它(实施安全机制)

I am trying to set the Content-MD5 header on a request created with the Jersey Client API. I have created ClientFilter which implements another adapter (similar to how the GZipFilter works). Like this:

public class ContentMD5Filter extends ClientFilter {

    private static final class ContentMD5Adapter extends AbstractClientRequestAdapter {
        ContentMD5Adapter(final ClientRequestAdapter cra) {
            super(cra);
        }

        @Override
        public OutputStream adapt(final ClientRequest request, final OutputStream out) throws IOException {
            try {
                MessageDigest instance = MessageDigest.getInstance("MD5");
                request.getHeaders().add("Content-MD5", instance);
                return new DigestOutputStream(out, instance);
            } catch (NoSuchAlgorithmException e) {
                throw new WebApplicationException();
            }
        }
    }

    @Override
    public ClientResponse handle(final ClientRequest cr) throws ClientHandlerException {
        cr.setAdapter(new ContentMD5Adapter(cr.getAdapter()));
        return getNext().handle(cr);
    }
}

This doesn't work, as the digest are read to early (ie. before the whole content is written.

Any ideas on how to do this? As well as setting the header, I need to access it in another filter afterwards (to implement a security mechanism)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

羅雙樹 2024-11-21 23:48:57

我找到了解决方案。这是一种相当复杂的方法,因为我必须临时存储输出流,但我想如果您自己需要的话,您可以弄清楚:)

过滤器的代码:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;

import com.sun.jersey.api.client.AbstractClientRequestAdapter;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.ClientRequest;
import com.sun.jersey.api.client.ClientRequestAdapter;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.filter.ClientFilter;

public class ContentMD5Filter extends ClientFilter {

    @Override
    public ClientResponse handle(final ClientRequest cr) throws ClientHandlerException {
        cr.setAdapter(new ContentMD5Adapter(cr.getAdapter()));
        return getNext().handle(cr);
    }

    private static final class ContentMD5Adapter extends AbstractClientRequestAdapter {
        ContentMD5Adapter(final ClientRequestAdapter cra) {
            super(cra);
        }

        @Override
        public OutputStream adapt(final ClientRequest request, final OutputStream out) throws IOException {
            return new ContentMD5OutputStream(request, getAdapter().adapt(request, out));
        }
    }

    private static final class ContentMD5OutputStream extends OutputStream {

        private final ByteArrayOutputStream byteArrayOutputStream;
        private final OutputStream jerseyStream;
        private final ClientRequest request;

        public ContentMD5OutputStream(final ClientRequest request, final OutputStream jerseyStream) {
            this.jerseyStream = jerseyStream;
            this.request = request;

            byteArrayOutputStream = new ByteArrayOutputStream();
        }

        @Override
        public void write(final int b) throws IOException {
            byteArrayOutputStream.write(b);
        }

        @Override
        public void close() throws IOException {
            byteArrayOutputStream.close();
            byte[] byteArray = byteArrayOutputStream.toByteArray();
            setContentMD5Header(byteArray);
            IOUtils.write(byteArray, jerseyStream);
            jerseyStream.close();
        }

        private void setContentMD5Header(final byte[] data) {
            try {
                MessageDigest instance = MessageDigest.getInstance("MD5");
                String contentMD5 = new String(Base64.encodeBase64(instance.digest(data)));
                request.getHeaders().add("Content-MD5", contentMD5);
            } catch (NoSuchAlgorithmException e) {
                // Errorhandling. Should not happen though!
            }
        }
    }
}

要使用此过滤器:

Client client = Client.create();
webResource = client.resource("http://localhost:8080/pathToYourResource");

contentMD5filter = new ContentMD5Filter();
webResource.addFilter(contentMD5filter);

I found the solution. It's a quite complex way to do it, since I have to temporarily store the outputstream, but I guess you can figure it out if you need this yourself :)

The code for the filter:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;

import com.sun.jersey.api.client.AbstractClientRequestAdapter;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.ClientRequest;
import com.sun.jersey.api.client.ClientRequestAdapter;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.filter.ClientFilter;

public class ContentMD5Filter extends ClientFilter {

    @Override
    public ClientResponse handle(final ClientRequest cr) throws ClientHandlerException {
        cr.setAdapter(new ContentMD5Adapter(cr.getAdapter()));
        return getNext().handle(cr);
    }

    private static final class ContentMD5Adapter extends AbstractClientRequestAdapter {
        ContentMD5Adapter(final ClientRequestAdapter cra) {
            super(cra);
        }

        @Override
        public OutputStream adapt(final ClientRequest request, final OutputStream out) throws IOException {
            return new ContentMD5OutputStream(request, getAdapter().adapt(request, out));
        }
    }

    private static final class ContentMD5OutputStream extends OutputStream {

        private final ByteArrayOutputStream byteArrayOutputStream;
        private final OutputStream jerseyStream;
        private final ClientRequest request;

        public ContentMD5OutputStream(final ClientRequest request, final OutputStream jerseyStream) {
            this.jerseyStream = jerseyStream;
            this.request = request;

            byteArrayOutputStream = new ByteArrayOutputStream();
        }

        @Override
        public void write(final int b) throws IOException {
            byteArrayOutputStream.write(b);
        }

        @Override
        public void close() throws IOException {
            byteArrayOutputStream.close();
            byte[] byteArray = byteArrayOutputStream.toByteArray();
            setContentMD5Header(byteArray);
            IOUtils.write(byteArray, jerseyStream);
            jerseyStream.close();
        }

        private void setContentMD5Header(final byte[] data) {
            try {
                MessageDigest instance = MessageDigest.getInstance("MD5");
                String contentMD5 = new String(Base64.encodeBase64(instance.digest(data)));
                request.getHeaders().add("Content-MD5", contentMD5);
            } catch (NoSuchAlgorithmException e) {
                // Errorhandling. Should not happen though!
            }
        }
    }
}

To use this filter:

Client client = Client.create();
webResource = client.resource("http://localhost:8080/pathToYourResource");

contentMD5filter = new ContentMD5Filter();
webResource.addFilter(contentMD5filter);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文