Asp.net Mvc4默認權限詳細(上)


前言

上篇的菜鳥去重復之Sql的問題還沒有得到滿意的答案。如果哪位大哥有相關的資料解釋,能夠分享給我,那就太謝謝了。

以后每發表一篇博文我都會將以前遺留的問題在前言里指出,直到解決為止。

本文主要在於探討一下Asp.net Mvc4默認生成的權限的詳細內容。

介紹

在VS2012中創建一個默認的帶有權限的MVC4 Internet項目,如下圖。

生成項目后點運行,在瀏覽器里點登陸。然后觀察項目,此刻生成了數據庫,如下。

本文就是針對這樣的模版項目里的已有權限全面的分析,希望大家能夠從中學到一些東西,如果有問題,請指出。PS:歡迎大家共同討論進步。

有趣的Attribute

上圖中有三個ActionFilter,不清楚ActionFilter的童鞋請點擊這里

AuthorizeAttribute:表示一個特性,該特性用於限制調用方對操作方法的訪問。

AllowAnonymousAttribute表示一個特性,該特性用於標記在授權期間要跳過 AuthorizeAttribute 的控制器和操作。

InitializeSimpleMembershipAttribute:這個特性是來初始化數據庫成員關系的,后面會講到。

Authorize

這個Attribute是用來對用戶角色權限限制的,大家應該都清楚,此處就不多說了。

AllowAnonymous

這個Attribute似乎是MVC4才加進去的。大致意思看一下上面的解釋應該也了解了。其實就是微軟團隊在Authorize的實現里面加了對AllowAnonymous的判斷,如果方法上有這個Attribute就不限制。

真相在這里(反編譯的),這個是Authorize的OnAuthorization方法,有興趣的童鞋可以看看12行

 1          public virtual void OnAuthorization(AuthorizationContext filterContext)
 2         {
 3             if (filterContext == null)
 4             {
 5                 throw new ArgumentNullException("filterContext");
 6             }
 7             if (OutputCacheAttribute.IsChildActionCacheActive(filterContext))
 8             {
 9                 throw new InvalidOperationException(MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache);
10             }
11             bool inherit = true;
12             if (!filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit) && !filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true))
13             {
14                 if (this.AuthorizeCore(filterContext.HttpContext))
15                 {
16                     HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
17                     cache.SetProxyMaxAge(new TimeSpan(0L));
18                     cache.AddValidationCallback(new HttpCacheValidateHandler(this.CacheValidateHandler), null);
19                 }
20                 else
21                 {
22                     this.HandleUnauthorizedRequest(filterContext);
23                 }
24             }
25         }

 

下面就到了主要的關於默認權限的關鍵Attribute。

InitializeSimpleMembership

我們先來看下它的實現

 1    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
 2    public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
 3     {
 4         private static SimpleMembershipInitializer _initializer;
 5         private static object _initializerLock = new object();
 6         private static bool _isInitialized;
 7 
 8         public override void OnActionExecuting(ActionExecutingContext filterContext)
 9         {
10             // Ensure ASP.NET Simple Membership is initialized only once per app start
11             LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
12         }
13 
14         private class SimpleMembershipInitializer
15         {
16             public SimpleMembershipInitializer()
17             {
18                 Database.SetInitializer<UsersContext>(null);
19 
20                 try
21                 {
22                     using (var context = new UsersContext())
23                     {
24                         if (!context.Database.Exists())
25                         {
26                             // Create the SimpleMembership database without Entity Framework migration schema
27                             ((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
28                         }
29                     }                  
30                     WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
31                 }
32                 catch (Exception ex)
33                 {
34                     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);
35                 }
36             }
37         }
38     }

這個Atrribute里面實現了創建我們起初見到的數據庫。

現在讓我們來看看具體是如何實現的。這個創建數據庫的方式還是和以前使用Code First有點出入的。

4-12行 主要是定義了幾個變量並重寫OnActionExcuting,實現了確保Asp.net成員關系只初始化一次。我們可以料到,必然在LazyInitializer.EnsureInitialized函數里面實例化了SimpleMembershipInitializer。

只初始化一次就意味着不會調用SimpleMembershipInitializer的構造函數兩次。其實看代碼我們應該也大致能猜到,這個構造函數里面主要做的就是創建數據庫的功能,當然最好只實現一次。

22-29行 主要就是調用方法創建UsersContext的數據庫,相關代碼如下

    public class UsersContext : DbContext
    {
        public UsersContext()
            : base("DefaultConnection")
        {
        }

        public DbSet<UserProfile> UserProfiles { get; set; }
    }

    [Table("UserProfile")]
    public class UserProfile
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int UserId { get; set; }
        public string UserName { get; set; }
    }

我們從上面可以了解到UsersContext繼承DbContext,並以DefaultConnection字符串為連接字符串,有一張表UserProfile。

那這時我們就會有疑問了,在文章開頭介紹里的那幾個標出來的表是如何生成的呢。先別急,我們繼續往下看

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

這句話的字面意思一看就猜到了。初始化數據庫連接使用連接字符串Default,表UserProfile,字段UserId,UserName,自動創建表。

可是我們之前已經使用UserContext的CreateDatabase()創建過數據庫和表了。難道再重新創建一次!!?好吧!還是讓我們看看MSDN的解釋吧!

InitializeDatabaseConnection()

通過連接到包含用戶信息的數據庫來初始化成員資格系統。

注釋

在應用程序啟動時調用此方法(在 _AppStart.cshtml 或 _AppStart.vbhtml 文件中),以初始化簡單成員資格系統。此方法驗證成員資格數據庫是否存在。它還打開到用戶配置文件表的連接,並在成員資格數據和用戶配置文件數據之間建立 數據庫關系。

如果希望使用包含用戶配置文件信息(用戶名、電子郵件地址等)的數據庫表,則應指定成員資格系統用於連接到那些信息的連接字符串和表名稱。如果不希望使用現有用戶配置文件表,則可指定 InitializeDatabaseConnection() 方法應自動創建用戶配置文件表。(用戶配置文件表的數據庫必須已經存在。)

下面是方法的五個參數解釋:

connectionStringName

包含用戶信息的數據庫的連接字符串的名稱。如果使用的是 SQL Server Compact,此名稱可以是一個不帶 .sdf 文件擴展名的數據庫文件(.sdf 文件)的名稱。

userTableName

包含用戶配置文件信息的數據庫表的名稱。

userIdColumn

包含用戶 ID 的數據庫列的名稱。此列必須以整數 (int) 形式鍵入。

userNameColumn

包含用戶名的數據庫列的名稱。此列用於匹配用戶配置文件數據與成員資格帳戶數據。

autoCreateTables

若為 true,則指示應創建用戶配置文件表和成員資格表(如果它們不存在)。若為 false,則指示不應自動創建這些表。雖然可以自動創建成員資格表,但數據庫本身必須已經存在。

我的理解

這個方法會對已有的數據庫進行分析,如果沒有提前創建數據庫,調用此方法會報錯。

如果已經創建一個空的數據庫並且不存在參數對應的userTableName表,設置autoCreateTables為true,會自動創建該參數名的表,字段與userIdColumn及userNameColumn一一對應,並創建其余的四個成員資格表。

如果設置autoCreateTables為false,不會自動創建任何表。

設置autoCreateTables為true,如果已經使用UserContext創建user表,要把表名與UserId、UserName的字段名作為參數賦給InitializeDatabaseConnection()方法作為參數,表名不一致,數據庫會多創建一個User表,並以方法參數名的那個來使用webSecurity的方法。字段名不一致,使用webSecurity的方法時會報錯。

至此,我們已經大致知道起初見到的那幾個數據表是如何生成的了。對,就是webSecurity.InitializeDatabaseConnection方法里自動實現的。

小結

本來打算把默認生成權限的這部分內容盡可能的在一篇里面說完,但寫本篇博客的過程中發現需要寫的有點多。

奈何我本是菜鳥,內容稍微多了點,就越發感覺腦子有點亂,所以打算分成兩篇來寫。

呵呵!目前還沒有實力寫長篇,那得需要思維足夠清晰,我還需要鍛煉啊!

下篇我打算寫一下WebSecurity,SimpleMemberShip,RoleProvider之間的關系,以及它們的使用場合Asp.net Mvc4默認權限詳細(下),希望有興趣的童鞋繼續關注!

最后,如果本文有什么問題,還請指出。如果對您有幫助,請幫忙推薦給我更多動力!

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM