0

私はこれを SharePoint 2010 で行っていますが、問題が SharePoint 2007 に存在し、同じ解決策があるとしても驚かないでしょう。

BDC データにランタイム セキュリティ トリマーがあります。モデルで定義された「デフォルト」のプロファイル URL に基づいて、セキュリティ トリマーが URL を提供することを期待していました。残念ながら、そうではありません。それは私に次のような URL を与えます:

このオブジェクトのプロパティを取得する必要があります (実際には主キーの値のみ)。BDC オブジェクト モデルでこれを行う方法はありますか? 次のリンクが参考になるようですが、上記の URL を使用するものは見たことがありません。

http://msdn.microsoft.com/en-us/library/ee556400.aspx


更新: SharePoint 2007 には AccessChecker (http://msdn.microsoft.com/en-us/library/aa981124.aspx) があり、2010 にもおそらくこれがあるようです (2010 に関する適切なドキュメントが見つかりません)。 . データベースにセキュリティ記述子を簡単に配置することはできませんが、AccessChecker メソッドで十分かもしれません。

もう少し掘り下げると、Microsoft.Office.Server.Search.Connector.BDC.BdcSecurityTrimmer が、SharePoint 2010 の AccessChecker で使用されている可能性が高いことがわかります。これは、URL ごとに DB にクエリを実行するようです。複数のスレッドで実行しても効率が悪いようです (2007 年のドキュメントではそう主張されています)。情報を 1 つの Web サービス呼び出しにまとめたいと思いますが、どうしようもありません...

4

2 に答える 2

1

OK、これが私の以前の答えの単純化です。反射を完全に回避できるようです:

using Microsoft.BusinessData.Runtime;
using Microsoft.Office.Server.Search.Connector;
using Microsoft.Office.Server.Search.Query;    

private string[] GetIds(IList<string> documentCrawlUrls)
{
    string[] ids = new String[documentCrawlUrls.Count];
    for (int i = 0; i < documentCrawlUrls.Count; i++)
    {
        try
        {
            string url = documentCrawlUrls[i];
            string id = new Microsoft.Office.Server.Search.Connector.UriParser(new Uri(url)).QueryStringParameters["s_id"];
            ids[i] = Identity.Deserialize(id).GetIdentifierValues()[0].ToString();
        }
        catch (Exception ex)
        {
            System.Diagnostics.Trace.WriteLine("Error: " + ex.Message);
        }
    }

    return ids;
}

次のようなコードを使用して、Microsoft.Office.Server.Search.Connector の UriParser の使用を避けようとしたことに注意してください。

string id = HttpUtility.ParseQueryString(new Uri(url).Query)["s_id"];
ids[i] = Identity.Deserialize(id.ToUpper()).GetIdentifierValues()[0].ToString();

残念ながら、これは一部の ID では機能し、他の ID では機能しませんでした。これ以上調査することはせず、特別な UriParser だけを使用することにしました。ある例では、私が探していた ID は「5,20,21,7,8,6,14,19,17,18,4」でしたが、この 2 番目のアプローチでは「5,20,21,24581,8, 24580,24588,24593,17,24592,4". 最初の 3 つは正しかったので、数分間混乱しました。

于 2010-09-29T16:30:34.220 に答える
0

これが最善の方法かどうかはわかりませんが、Reflector を使用して Microsoft.Office.Server.Search.Connector.BDC.BdcSecurityTrimmer をリバース エンジニアリングすることで、これを機能させることができました。これを少し単純化するために、ID 値のみが必要でした。

以下は、セキュリティ トリマーに提供された documentCrawlUrls の配列を取得し、BDC モデル ファイルで定義されている主キーの配列に変換するコードです。それらを取得したら、さらにカスタム .NET コードを使用してセキュリティ トリミングを決定できます。

私のセキュリティ トリマー (ISecurityTrimmer2) の CheckAccess() には、次のものがあります。

String[] ids = GetIds(documentCrawlUrls);

次に、次のプライベートメソッドがあります。

private string[] GetIds(IList<string> documentCrawlUrls)
{
    string[] ids = new String[documentCrawlUrls.Count];
    for (int i = 0; i < documentCrawlUrls.Count; i++)
    {
        try
        {
            string url = documentCrawlUrls[i];

            Identity identity = null;
            IEntity entity = null;
            ILobSystemInstance lsi = null;
            ParseUri(url, out entity, out identity, out lsi);
            if (identity != null)
            {
                object[] values = identity.GetIdentifierValues();
                if (values.Length > 0)
                {
                    ids[i] = values[0].ToString();
                }
            }
        }
        catch (Exception ex)
        {
            System.Diagnostics.Trace.WriteLine("Error: " + ex.Message);
        }
    }

    return ids;
}

私は SPBdcUri クラスを書き直したくありませんでした。これは内部であるため、リフレクションでごまかします。現在、効率を改善できるように、out パラメータの 1 つだけを使用しています。リフレクションに頼るのではなく、SPBdcUri の必要な部分を書き直すことができます。

private void ParseUri(string crawlUri, out IEntity entity, out Identity identity, out ILobSystemInstance lsi)
{
    //SPBdcUri uri = new SPBdcUri(new Uri(crawlUri));
    AssemblyName assemblyName = new AssemblyName("Microsoft.Office.Server.Search.Connector, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");
    Assembly assembly = Assembly.Load(assemblyName);
    Type spBdcUriType = assembly.GetType("Microsoft.Office.Server.Search.Connector.BDC.SPBDC.SPBdcUri");
    object uri = Activator.CreateInstance(spBdcUriType,
        BindingFlags.NonPublic | BindingFlags.Instance,
        null, new object[] { new Uri(crawlUri) }, System.Globalization.CultureInfo.CurrentCulture);

    //uri.DoOverrideBDCThrottlingLimits = false;
    spBdcUriType.InvokeMember("DoOverrideBDCThrottlingLimits",
        BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
        null, uri, new object[] { false });

    //entity = uri.Entity;
    object entityObj = spBdcUriType.InvokeMember("Entity",
        BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty,
        null, uri, null);
    entity = (IEntity)entityObj;

    //identity = uri.Identity;
    object identityObj = spBdcUriType.InvokeMember("Identity",
        BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty,
        null, uri, null);
    identity = (Identity)identityObj;

    //lsi = uri.LobSystemInstance;
    object lsiObj = spBdcUriType.InvokeMember("LobSystemInstance",
        BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty,
        null, uri, null);
    lsi = (ILobSystemInstance)lsiObj;
}

ああ、ここに私の「使用」ステートメントがあります:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

using Microsoft.BusinessData.MetadataModel.Collections;
using Microsoft.BusinessData.MetadataModel;
using Microsoft.BusinessData.Runtime;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.BusinessData.SharedService;
using Microsoft.Office.Server.Search.Query;
于 2010-09-29T03:57:24.117 に答える