Authentication problems after publishing MVC 4 app to azure

吃可爱长大的小学妹 提交于 2019-11-29 06:46:16

After trying dozens of different suggestions from various blog posts, I have found a solution. Adding the InitialiseSimpleMembership attribute to my home controller resolves the problem.

[InitializeSimpleMembership]
public class HomeController : Controller

After making this change, I managed several successful publishes without issues. I suspect the reason is that the following line of code in the InitializeSimpleMembershipAttribute constructor needs to run before any calls to User.IsInRole are made:

WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);

I guess the best thing to do would be to run InitializeSimpleMembership in Application_Start.

Here's a tutorial that you could follow to setup a SQL database when deploying your application on Windows Azure. You must setup the correct connection string in your web.config which by default is pointing to a local SQL Express database when you create a new ASP.NET MVC 4 application using the Internet template.

Your SQL Azure connection string will look something like this:

<connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=tcp:#server#.database.windows.net,1433;Initial Catalog=#DBName#;User ID=UserName#@#server#;Password=#password#;MultipleActiveResultSets=True" providerName="System.Data.SqlClient"/>
</connectionStrings>

Although this question has been answered, I thought I might quickly share my experiences with the same problem. My case is slightly different to Mark's.

So, I had the InitializeSimpleMembership attribute on all my controllers (actually I had it on my base controller from which all my controllers inherit), however I was still experiencing the same problem. Now, in my base controller I was also overriding the Initialize method in order to setup some context information for our application. Part of this context setup is to check if the current user is in a particular role, hence the IsUserInRole method was being called from within this Initialize method, all before any action method is being called.

Now if one takes a look at the InitializeSimpleMembership class one notices that the initializing is actually done in the OnActionExecuting method (i.e. InitializeSimpleMembership inherits from ActionFilterAttribute):

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
      // Ensure ASP.NET Simple Membership is initialized only once per app start
      LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}

In my case, this membership initialization was happening too late...that is, I need the Simple Membership to be initialized before I make my call to IsUserInRole in my base controller's overridden Initialize method.

The solution for me was relatively simple: I removed the InitializeSimpleMembership attribute entirely and put its logic straight into my base controller so that I could call it from my Initialize method, something like this:

public class BaseController : Controller
{
    private static SimpleMembershipInitializer _initializer;
    private static object _initializerLock = new object();
    private static bool _isInitialized;

    private class SimpleMembershipInitializer
    {
        public SimpleMembershipInitializer()
        {
            try
            {
                WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
            }
        }
    }

    ...

    protected override void Initialize(RequestContext requestContext)
    {
        base.Initialize(requestContext);
        LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
        SetupControllerContext(); // my function that calls 'IsUserInRole'
    }
}

Now I imagine that one should probably refactor this and put it in the Application_Start() method, as Mark suggested, but you get the idea :). I just wanted to explain my experience just in case anybody is doing something similar in their controller's overridden Initialize method.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!