如何使 Jackrabbit WebDAV servlet 允许使用 Microsoft Word 进行编辑?

Posted

技术标签:

【中文标题】如何使 Jackrabbit WebDAV servlet 允许使用 Microsoft Word 进行编辑?【英文标题】:How to make Jackrabbit WebDAV servlet allow editing with Microsoft Word? 【发布时间】:2019-05-29 20:07:06 【问题描述】:

我正在尝试通过 servlet 公开 Jackrabbit Oak 存储库。虽然我能够使用 LibreOffice Writer 成功检索和编辑 .docx 文件,但 Microsoft Word 不起作用。

我正在使用:

Jackrabbit Oak 1.8.4 版 Jackrabbit 版本 2.17.5 LibreOffice Writer 版本 6.1.3.2

Word 不工作的版本是:

版本 1708 Microsoft Office 365 专业增强版。

我通过使用打开文档对话框并输入http://localhost:8080/helloworld-singleton/repository/default/test.docx,在两个编辑器中类似地访问文档

我使用 OpenSecurityProvider 设置了一个简单的 servlet,它公开了一个复制简单 .docx 文档的本地副本的存储库:

public class SimpleWebdavServlet extends SimpleWebdavServlet 
  private static Repository repository;

  public Repository getRepository() 
    return getRepositoryInternal();
  

  static Repository getRepositoryInternal() 
    try 
      if (repository == null) 
        Jcr jcr = new Jcr().with(new OpenSecurityProvider());
        repository = jcr.createRepository();
        Session session = repository.login(new SimpleCredentials("admin", "admin".toCharArray()));

        Node rootNode = session.getRootNode();
        if (!rootNode.hasNode("test.docx")) 
          importFile(session, rootNode);
        
        session.save();
      
     catch (FileNotFoundException | RepositoryException e) 
      e.printStackTrace();
    
    return repository;
  

  private static void importFile(Session session, Node rootNode) throws FileNotFoundException, RepositoryException 
    FileInputStream is = new FileInputStream(new File("C:\\test.docx"));
    ValueFactory valueFactory = session.getValueFactory();
    Binary contentValue = valueFactory.createBinary(is);
    Node fileNode = rootNode.addNode("test.docx", "nt:file");
    fileNode.addMixin("mix:referenceable");
    Node resNode = fileNode.addNode("jcr:content", "nt:resource");
    resNode.setProperty("jcr:mimeType", "application/octet-stream");
    resNode.setProperty("jcr:data", contentValue);
    Calendar lastModified = Calendar.getInstance();
    lastModified.setTimeInMillis(lastModified.getTimeInMillis());
    resNode.setProperty("jcr:lastModified", lastModified);
    session.save();
  

这个servlet是通过下面的web.xml配置的:

<web-app>
  <display-name>Jackrabbit Webdav</display-name>
  <servlet>
    <servlet-name>Webdav</servlet-name>
    <servlet-class>org.jboss.as.quickstarts.singleton.SimpleWebdavServlet</servlet-class>
    <init-param>
      <param-name>resource-path-prefix</param-name>
      <param-value>/repository</param-value>
    </init-param>
    <init-param>
      <param-name>missing-auth-mapping</param-name>
      <param-value>admin:admin</param-value>
    </init-param>
    <init-param>
      <param-name>resource-config</param-name>
      <param-value>/WEB-INF/config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>Webdav</servlet-name>
    <url-pattern>/repository/*</url-pattern>
  </servlet-mapping>
</web-app>

使用此代码,我希望能够在 Word 中打开文档,对其进行编辑,然后将更改保存到服务器 - 就像在 LibreOffice Writer 中一样。

与 Word 不同,该文档以受保护的视图打开,尝试保存更改时,系统只会提示您保存它的本地副本。

我尝试为另一个 JCR 实现 ModeShape 制作一个类似的 servlet,并且在那里通过 Word 持久化文档没有遇到任何问题。

作为在 Jackrabbit 内部调试时可能的解释,编辑器之间的一个明显区别是 LibreOffice Writer 在 Authorization 标头中发送 null,而 Word 在 Authorization 标头中发送 Bearer这是请求。由于org.apache.jackrabbit.webdav.DavException: Unable to decode authorization. 的异常,所有这些请求都将被忽略

有人知道为什么 Word 在这种情况下不能按预期工作吗?

【问题讨论】:

FWIW,但与您的问题无关:不要在生产代码中使用不稳定的 Jackrabbit 版本(2.17 == 奇数 == 不稳定)。 【参考方案1】:

我确认 jackrabbit-jcr-server 不支持“授权:承载”。 BasicCredentialsProvider 类仅支持“login:password”base64 编码的基本身份验证。

出于测试目的,我修改了 getCredentials() 方法以在收到承载授权时强制使用“admin/admin”进行基本身份验证:

...
if (authStr.length >= 2 && authStr[0].equalsIgnoreCase(HttpServletRequest.BASIC_AUTH)) 
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    Base64.decode(authStr[1].toCharArray(), out);
    String decAuthStr = out.toString("ISO-8859-1");
    int pos = decAuthStr.indexOf(':');
    String userid = decAuthStr.substring(0, pos);
    String passwd = decAuthStr.substring(pos + 1);
    return new SimpleCredentials(userid, passwd.toCharArray());
 else if (authStr.length >= 1 && authStr[0].equalsIgnoreCase("Bearer")) 
    return new SimpleCredentials("admin", "admin".toCharArray());

throw new ServletException("Unable to decode authorization.");
...

之后我重新编译了jackrabbit-jcr-server(使用maven)并重新部署它,然后使用MS Word的直接版本就可以了。

现在应该做一个更好的实现......

【讨论】:

您好,您可以在您的项目中覆盖 CredentialsProvider 的实现,因此无需更改 Jackrabbit 源。我可以这样做,但我无法真正打开 Word 文档,您是否成功地直接使用 Word 打开/编辑?

以上是关于如何使 Jackrabbit WebDAV servlet 允许使用 Microsoft Word 进行编辑?的主要内容,如果未能解决你的问题,请参考以下文章

apache jackrabbit 实现 webdav 客户端怎么设置主体

apache jackrabbit 实现 webdav 客户端怎么设置主体

jdk1.6下使用sardine和jackrabbit-webdav的问题

jdk1.6下使用sardine和jackrabbit-webdav的问题

Jackrabbit仓库的运维管理

如何在不关闭 Jackrabbit 的情况下备份 apache Jackrabbit 存储库?