How to use ASP.NET Identity for Temporary Administ

2019-09-08 05:51发布

问题:

I am creating a new website, and it's already online, but I want to block access to everyone! And just let my client use it to check the development process everyday, so he don't need to download everything and set up on his computer..

I was wondering about using ASP Identity, is there any simple "hack" to achieve this?

Or my only way is the following:

  1. Add the Register Page to the WebSite
  2. Register an account with Administrator role
  3. Delete Register Page of the WebSite
  4. Use always the same account to check the page

Waiting for an answer, how to simply and easily achieve this?

EDIT: Maybe there is a way to create a default username (that in this case will be my Administrator?)

Thank you! Thank you very much!

回答1:

As the user @trailmax suggested I was not choosing the best place to insert default users for Identity, since I was inserting the users each time the constructor of the context was called.

After analysis of course that's not a good option, because every time I access my DbSets I use the context constructor, triggering additional sql queries to Roles and Users DbSets, without need (because I only need that query on the startup to insert the users if they don't exist).

So.. since my web-hosting plan don't allow any Update Migrations neither Seed Methods to be runnable from Package Manager Console (because it always reference the 'master' database which I don't have permissions), I figured out this solution:

1) I create all my tables running a sql script on my remote mssql database (to get the generated SQL Script from my contexts and models, I type the following command in Package Manager Console:

Update-Database -Script -SourceMigration:0

2) Then I need to set Database Initializer to null, so EF doesn't try to drop/create a Database and finnaly I just invoke a method on my Context Class from my Global.asax in the method Application_Start:

protected void Application_Start()
{
     AreaRegistration.RegisterAllAreas();
     FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
     RouteConfig.RegisterRoutes(RouteTable.Routes);
     BundleConfig.RegisterBundles(BundleTable.Bundles);
     Database.SetInitializer<MyContext>(null);
     new MyContext().CreateDefaultUsers();
}

3) And here is my method, that is only called on Application Startup (I am almost sure about it, at least I hope so, I wanna save CPU Clocks!)

public class MyContext : IdentityDbContext<IdentityUser>
{
        public MyContext() : base("MyContext")
        {
        }


        internal void CreateDefaultUsers()
        {
            if (!Roles.Any(r => r.Name == "admin"))
            {
                var RoleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(this));
                RoleManager.Create(new IdentityRole("admin"));
            }


            if (!Users.Any(u => u.UserName == "myadmin"))
            {
                var store = new UserStore<IdentityUser>(this);
                var manager = new UserManager<IdentityUser>(store);

                var user = new IdentityUser { UserName = "myadmin" };

                manager.Create(user, "mysupersafepwlulz");
                manager.AddToRole(user.Id, "admin");
            }
        }
     //More stuff not relevang for the question...

}

I hope this helps someone out there, and thank you @trailmax !



回答2:

So I manage to this with a specific DbContext that creates my default user if he doesn't exist on the Database.

Here is the follow up code:

namespace MyNamespace
{
    public class MyContext: IdentityDbContext<IdentityUser>
        {

            public MyContext() : base("DefaultConnection")
            {
                if (!Roles.Any(r => r.Name == "admin"))
                {
                    var RoleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(this));
                    RoleManager.Create(new IdentityRole("admin"));
                }                


                if (!Users.Any(u => u.UserName == "mydefaultuser"))
                {
                    var store = new UserStore<IdentityUser>(this);
                    var manager = new UserManager<IdentityUser>(store);

                    var user = new IdentityUser { UserName = "mydefaultuser" };

                    manager.Create(user, "password");
                    manager.AddToRole(user.Id, "admin");
                }
            }

            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
                modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
            }

            public DbSet<MyItem1> myStuff1 { get; set; }
            public DbSet<MyItem2> myStuff2 { get; set; }
            public DbSet<MyItem3> myStuff3 { get; set; }
            public DbSet<MyItem4> myStuff4 { get; set; }
            public DbSet<MyItem5> myStuff5 { get; set; }
        }
}

Then I needed to specify the config class for the Identity creating this class on App_Start:

namespace MyNamespace
{
    public class IdentityConfig
        {
            public void Configuration(IAppBuilder app)
            {
                app.CreatePerOwinContext(() => new WeirdMachineContext());
                app.UseCookieAuthentication(new CookieAuthenticationOptions
                {
                    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                    LoginPath = new PathString("/Home/Login"),
                });
                FormsAuthentication.SetAuthCookie("CookieValue", false);
            }
        }
}

And last I had to add the following in Web.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections></configSections>
  <appSettings>
    <!-- A lot of other stuff here.. -->
    <add key="owin:AppStartup" value="MyNamespace.IdentityConfig" />
  </appSettings>
    <!-- More stuff here.. -->
</configuration>

I hope it helps someone out there ;)

Good luck!



回答3:

How secure do you need this to be? You could go about it in another fashion, by restricting by IP.

Option 1 - Only allow specific IPs to your site

I'd recommend blocking all access to the site in your web.config and only whitelist the IP(s) that you and the client would be connecting from - it'll save you time, and it would ensure that you're only getting connections from IPs you trust.

Modify the appropriate web.config

<configuration>
  <system.webServer>
    <security>
      <ipSecurity allowUnlisted="false">                    
        <clear/> 
        <add ipAddress="127.0.0.1" allowed="true"/> 
        <add ipAddress="x.x.x.x" allowed="true"/>   <!-- your internal or external ip -->
        <add ipAddress="x.x.x.x" allowed="true"/>   <!-- your client's ip -->
        <add ipAddress="a.b.c.0" subnetMask="255.255.255.0" allowed="true"/>  <!-- your IP range (or client's IP range), if connecting from multpipe IPs on same subnet -->
      </ipSecurity>
    </security>
  </configuration>
</system.webServer>

Add as many <add> directives as needed

Option 2 - add basic authentication to web.config

This is not a permanent solution. Look into other authentication methods for long term.

<system.web>      
  <authentication mode="Forms">      
    <credentials passwordFormat="Clear">      
      <user name="jdoe1" password="someinsecurepassword" />      
    </credentials>      
  </authentication>      
  <authorization>      
    <allow users="jdoe1" />      
    <deny users="*" />      
  </authorization>      
</system.web>