Могу ли я обеспечить строгую проверку данных base64Binary в JAX-WS? - PullRequest
4 голосов
/ 16 мая 2011

tl; dr версия: есть ли способ принудительно установить строгий режим для JAX-WS, который отклоняет недопустимый base64 для типа данных base64Binary XSD?


Более длинная версия: у меня есть вебслужба, которая получает двоичные данные, которые сопоставляются с типом XSD base64Binary.При тестировании сервиса я обнаружил, что JAX-WS очень снисходительно относится к разбору строк Base64.Независимо от того, насколько неверным был мой ввод, я не мог заставить JAX-WS выдавать ошибку.

Я создал небольшой тестовый сервис и клиент, который иллюстрирует проблему.Его можно скопировать более или менее дословно:

Интерфейс службы:

@WebService
public interface ITest2 {
    @WebMethod
    void foo(byte[] bs);
}

Реализация и тестирование службы:

@WebService(endpointInterface="foo.bar.ITest2")
public class Test2 implements ITest2 {

    private static final String requestTemplate = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:bar=\"http://bar.foo/\">" +
            "<soapenv:Header/>" +
            "<soapenv:Body>" +
            "<bar:foo>" +
            "<arg0>%s</arg0>" +
            "</bar:foo>" +
            "</soapenv:Body>" +
            "</soapenv:Envelope>";

    private static final String[] testVector = {
        "////==",
        "///==",
        "//==",
        "/==",
        "/==/==/==",
        "&lt;&gt;",
        "=====",
        "%%%///%%%==%%"
    };

    private static PrintWriter pw;

    static {
        try {
            pw = new PrintWriter("/tmp/output");
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) throws Exception {

        Endpoint e = Endpoint.publish("http://localhost:54321/foo", new Test2());

        URL requestUrl = new URL("http://localhost:54321/foo");

        for(String testVal : testVector) {
            pw.println("[client] >" + testVal + "<");
            HttpURLConnection urlc = (HttpURLConnection) requestUrl.openConnection();
            urlc.setRequestProperty("Content-Type", "text/xml;charset=UTF-8");

            urlc.setDoOutput(true);

            OutputStream out = urlc.getOutputStream();

            String request = String.format(requestTemplate, testVal);

            out.write(request.getBytes());
            out.flush();

            InputStream in = urlc.getInputStream();
            int read = -1;
            byte[] buf = new byte[1024];
            while((read = in.read(buf)) != -1) {
                System.err.print(new String(buf, 0, read));
            }
            System.err.println();
        }

        pw.flush();
        pw.close();

    }

    @Override
    public void foo(byte[] bs) {
        String encoded;
        if(bs == null) {
            encoded = "<null>";
        } else if(bs.length == 0) {
            encoded = "<empty>";
        } else {
            encoded = new String(Base64.encodeBase64(bs));
        }
        pw.println("[server] >" + encoded + "<");
    }

}

В результате вы получите следующий вывод в / tmp / output (я использую Jetty, которая довольно часто записывает на консоль и не хотела беспокоиться об этом):

[client] >////==<
[server] ><null><
[client] >///==<
[server] ><null><
[client] >/w==<
[server] >/w==<
[client] >/==<
[server] ><null><
[client] >/==/==/==<
[server] >/////w==<
[client] >&lt;&gt;<
[server] ><empty><
[client] >=====<
[server] >/w==<
[client] >%%%///%%%==%%<
[server] >//8=<

Так что это полный беспорядок.Иногда я получаю null, иногда пустую строку, а иногда мусор заменяется другим мусором.Также каждый запрос генерирует HTTP-ответ 200, так что никто не знает, что где-то что-то пошло не так.

Я знаю, что вы можете заставить JAXB проверить это, добавив схему в Unmarshaller.Поскольку JAX-WS использует JAXB для внутреннего использования, я надеюсь, что есть возможность включить это и для веб-сервисов.Кто-нибудь знает, возможно ли это и как?

Я использую стандартную реализацию JAX-WS из Oracle Java 1.6.0_24 в Ubuntu.

1 Ответ

1 голос
/ 16 мая 2011

Вы можете включить проверку схемы в Metro (JAXWS-RI), добавив com.sun.xml.internal.ws.developer.SchemaValidation аннотацию в вашей реализации конечной точки - Test2.

Это вызывает ошибку SOAPформа:

...
<S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope">
  <faultcode>S:Server</faultcode>
  <faultstring>com.sun.istack.internal.XMLStreamException2:
       org.xml.sax.SAXParseException: cvc-datatype-valid.1.2.1: 
       'foo' is not a valid value for 'base64Binary'.</faultstring>
...

Технически я считаю, что код ошибки должен быть S:Client, но что я знаю.

Насколько я знаю, не существует способа, независимого от реализации;поэтому, если вы развернете код в другом контейнере JAX-WS, вам придется использовать механизм для этого контейнера.

...