SessionAsSigner& restoreWrappedDocument()

时间:2016-01-28 10:25:03

标签: xpages

面对以下问题:我在项目中积极使用DominoDocument类(包装文档),特别是作为业务模型对象的基础。

我经常需要以匿名用户身份访问/迭代我的业务模型对象,因此基于SessionAsSigner会话对象检索lotus.domino.Document(例如,在某些REST服务的情况下,或者在xAgent的情况下,等等) )。

在这种情况下,restoreWrappedDocument()方法的行为确实破坏了使用此类体系结构的所有灵活性:此方法尝试根据当前执行环境访问权限恢复包装文档,当然这会导致ACL出错。

我们将以下代码片段视为示例:

public void test3() {
    try {

        System.out.println(">>>>>");
        System.out.println(">>>>> START");

        lotus.domino.Database db = AppBean.getSessionAsSigner().getDatabase(AppBean.getInstance().getContactsDBserverName(), AppBean.getInstance().getContactsDBname(), false);

        Document notesDoc = db.getAllDocuments().getFirstDocument();
        String dbName = notesDoc.getParentDatabase().getServer() + "!!" + notesDoc.getParentDatabase().getFilePath();
        DominoDocument ds = DominoDocument.wrap(dbName, notesDoc, null, "exception", false, "UseWeb", null);

        System.out.println(">> 1 >> " + ds.getValue("form"));

        ds.getDocument().recycle();

        try {
            ds.restoreWrappedDocument();
        }catch(Throwable e2){
            System.out.println(">> 2 - exception - >> " + e2.toString());
            e2.printStackTrace();
        }

        try {
            System.out.println(">> 3 >> " + ds.getValue("form"));
        }catch(Throwable e3){
            System.out.println(">> 3 - exception - >> " + e3.toString());
        }

        System.out.println(">>>>> END");
        System.out.println(">>>>>");

    }catch(Exception e){
        e.printStackTrace();
    }
}

1)场景1:由有权访问目标数据库的经过身份验证的用户执行此代码会产生以下结果:

enter image description here

所以方法按预期工作,一切都很完美。

2)场景2:匿名用户执行此代码会导致异常(通常是预期的):

enter image description here

您可以清楚地看到restoreWrappedDocument()执行一些帮助方法以获取数据库,当然这是使用当前用户访问级别(匿名)完成的。

可能的解决方案:

  1. 显而易见的解决方案是将自定义逻辑添加到我的业务对象模型中,该模型将执行自定义恢复(基本上基于服务器和数据库名称以及文档UNID或NoteID)。
  2. 我是否非常好奇是否有更多智能或内置方法可以使用SessionAsSigner权限恢复包装文档?
  3. 谢谢!

2 个答案:

答案 0 :(得分:1)

除了你的选择1之外,我认为没有一种正确的方法可以做到这一点,无论好坏。

但是,我并不是说这是的想法,似乎DominoDocument可能会通过当前的请求映射进入其会话。如果您想要变得棘手,可以尝试在请求范围内暂时替换session sessionAsSigner,调用restoreWrappedDocument,然后将其交换回来。

答案 1 :(得分:1)

使用Java Reflection的Helper类的解决方案: (不完整,遗漏了一些部分)

package ch.hasselba.xpages;

import java.lang.reflect.Field;

import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.NotesException;

import com.ibm.xsp.FacesExceptionEx;
import com.ibm.xsp.model.domino.DominoUtils;
import com.ibm.xsp.model.domino.wrapped.DominoDocument;

public class DominoDocumentUtil {

    private static final long serialVersionUID = 1L;
    private transient final Field wrappedObj;
    private transient final DominoDocument dominoDoc;

    public DominoDocumentUtil(DominoDocument doc) throws SecurityException,
            NoSuchFieldException {
        dominoDoc = doc;
        wrappedObj= doc.getClass().getDeclaredField("_wrappedObject");
        wrappedObj.setAccessible(true);
    }

    public void restoreWrappedDocument(Database db)
            throws IllegalArgumentException, IllegalAccessException {
        try {
            Document doc = DominoUtils.getDocumentById(db, dominoDoc
                .getDocumentId(), dominoDoc.isAllowDeletedDocs());
            this.wrappedObj.set(dominoDoc, doc);
        } catch (NotesException ne) {
            throw new FacesExceptionEx(ne.getMessage());
        }
    }
}

要使用该类,您可以使用 sessionAsSigner 打开的数据库调用 restoreWrappedDocument 方法:

DominoDocumentUtil util = new DominoDocumentUtil(ds);
util.restoreWrappedDocument(db);