1

我有一个 WCF 服务,它有一个继承 System.Web.Security.RoleProvider 的类。在本课程中,我使用授权管理器 (AzMan) - 使用 AzRoles.dll - 进行角色管理。

身份验证在 ADAM 实例中。

我的服务在负载下遇到问题,似乎我需要更改服务,以便每次调用都打开和关闭 AzMan 商店 - 否则不会释放对象,最终应用程序池会崩溃 - 至少这样似乎正在发生的事情 - 我无法确认这 100%。

在原始代码中,AzMan 存储在重写的 Initialize 方法中被初始化,如下所示:

public class AzManProvider : RoleProvider {
.
.
.
    public override void Initialize( string name, System.Collections.Specialized.NameValueCollection config ) {
                base.Initialize( name, config );
                if ( config != null ) {
                    string appName = null;
                    string connStr = null;
                    foreach ( string k in config.Keys ) {
                        string key = k.ToLower().Trim();
                        string value = config[k];
                        if ( key == "applicationName".ToLower() ) {
                            appName = value;
                        } else if ( key == "connectionStringName".ToLower() ) {
                            connStr = ConfigurationManager.ConnectionStrings[value].ConnectionString;
                        }
                    }
                    if ( connStr.IsEmpty() )
                        throw new ArgumentNullException( "connectionStringName" );
                    CurrentApplicationName = appName;
                    m_azManStore = new AzAuthorizationStoreClass();
                    try {
                        m_azManStore.Initialize( 0, connStr, null );
                    } catch ( Exception ex ) {
                        throw ex;
                    }
                }
            }
.
.
.
}

我不确定何时准确调用此方法。如果你在 VS 中运行它并设置一个断点,它永远不会命中。此类通过在该部分的 web.config 中设置对它的引用来实例化。

经过大量研究后,我发现了这篇博客文章,其中提出了一种将 AzMan 商店包装在一次性类中的方法 - 很简单。我创建了一个实现 IDisposable 的类:

public class AzManHelper : IDisposable
    {
        public IAzAuthorizationStore Store { get; private set; }
        public IAzApplication Application { get; private set; }

        public AzManHelper(string appName)
        {
            string connStr = ConfigurationManager.ConnectionStrings["AzMan"].ConnectionString;

            try
            {
                    this.Store = new AzAuthorizationStoreClass();
                    this.Store.Initialize(0, connStr, null);   //<-- Exception occurs here
                    this.Store.UpdateCache(null);
                    if (!String.IsNullOrEmpty(appName))
                        this.Application = this.Store.OpenApplication(appName, null);
            }
            catch (COMException cex)
            {
                HandleCOMException(cex);
            }
        }

        public void Dispose()
        {
            if (this.Application == null) 
                return;

            Marshal.FinalReleaseComObject(this.Application);

            if(this.Store != null)
                Marshal.FinalReleaseComObject(this.Store);

            this.Application = null;
            this.Store = null;
        }
}

现在,当我运行此代码时,当调用 AzMan 存储上的 Initialize 方法时,我得到一个 FileNotFoundException。我已经确认连接字符串是正确的。

特别令人沮丧的是,如果我在 VS 2010 中本地运行此代码,但如果我将其部署并作为 WCF 服务运行,我会收到我提到的错误,即使用户 ID 和 LDAP 连接字符串相同。

我阅读了这篇博文并发布了文章

然后我认为可能初始化方法正在运行,无论 IIS 应用程序池正在运行什么,并且外部的代码作为模拟用户运行。因此,使用一位同事编写的特殊类,我在调用 AzMan 初始化方法时关闭了模拟。我确认用户是网络服务,但我仍然得到相同的 FileNotFoundException。我一直在与 IT 人员合作尝试不同的权限设置,但到目前为止还没有运气。

有人知道我为什么会收到此错误吗?我应该查看哪些权限?

也许我使用 AzMan 的方法是错误的——我的架构是否存在缺陷(除了我正在使用 AzMan 的事实?)

4

1 回答 1

1

我发现了我的问题。我的 WCF 服务托管在 IIS 中。web.config 文件中有一个标签。模拟是针对服务运行的服务帐户。当 WCF 服务托管在 IIS 中时,ASP.NET 用于启动该服务,仅此而已。因此,当应用程序启动时,AzManProvider 类由 ASP 初始化,因此模拟正在完成。Initialize 方法在类被实例化时被调用。服务帐户有权打开 AzMan。对 WCF 服务的调用不使用 web.config 中的任何 ASP 配置设置。因此,服务调用以应用程序池的身份运行 - NETWORK SERVICE。为了解决这个问题,我们将应用程序池标识更改为作为服务帐户运行 - 并从 web.config 中删除了标记。现在,一切正常。

我不明白为什么没有安全权限会引发 FileNotFound 异常。

于 2011-01-24T22:41:45.630 回答