Calling initialize method of AzMan object causes F

2019-05-29 23:48发布

问题:

I have A WCF service that has a class that inherits System.Web.Security.RoleProvider. In this class I use Authorization Manager (AzMan) - using AzRoles.dll - for role management.

Authentication is in an ADAM instance.

I have been having trouble with my service under load and it seemed like I need to change the service so that the AzMan store was opened and closed for each call - otherwise objects were not being released and eventually the app pool would crash - at least that is what seems to be going on - I have been unable to confirm this 100%.

In the original code the AzMan store was initialized in the overridden Initialize method like this:

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;
                    }
                }
            }
.
.
.
}

I am not sure when this method is called exactly. If you run it in VS and put a break point, it will never hit. This class is instantiated by setting a reference to it in the web.config in the section.

After doing a lot of research I came across this blog post that suggested a way to wrap the AzMan store in a disposable class - easy enough. I created a class that implements 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;
        }
}

Now, when I run this code I get a FileNotFoundException when the Initialize method on the AzMan store is called. I have confirmed that the connection string is correct.

What is especially frustrating is that this code will work if i run it locally within VS 2010 but if I deploy it and run it as a WCF service I get the error I mentioned eventhough the userID and LDAP connect string are the same.

I read this blog post and posted article

I then thought that maybe the initialize method is being run as whatever the IIS App pool is running as and the code outside of that is run as the imperonated user. So, using a special class that a collegue wrote, I turned off impersonation when calling the AzMan intialize method. I confirmed that the user was NETWORK SERVICE but I STILL get the same FileNotFoundException. I have been working with out IT guys to try different permission settings but so far no luck.

Does anybody have any idea as to why I am getting this error? What permissions should I be looking at?

Perhaps my approach to using AzMan is wrong - is my architecture flawed (besides the fact that I am using AzMan?)

回答1:

I figured out my problem. My WCF service is hosted in IIS. The web.config file had an tag in it. The impersonation was for a service account that the service was to run as. When a WCF service is hosted in IIS the ASP.NET is used to launch the service but that's it. So, when the app started up the AzManProvider class was initialized by ASP so the impersonation was being done. The Initialize method is called at the time the class is instantiated. The servcice account has rights to open AzMan. Calls to the WCF service do not use any of the ASP condifuration settings in web.config. So, the service calls run under the identity of the application pool - NETWORK SERVICE. To fix this, we changed the app pool identity to run as the service account - and removed the tag from the web.config. Now, everything works.

I don't understand why not having security permissions would throw a FileNotFound exception.