2013-02-25 72 views
0

我想確保我在正確的軌道與這一項上。MVC3多用戶/連接字符串

我有一個網站有兩個後端區域,一個用於學校,另一個用於管理員。我想驗證使學校面積少DB的權限比管理的區域。要做到這一點我的想法是在SQL Server Management Studio中學校和管理,這是我可以映射到某些角色兩次登錄。也許學校的部分將具有隻讀訪問和管理讀寫等。

請可有人告訴我,以着手實施這個的最佳方式。我是否需要多個連接字符串(一個用於管理,一個用於學校)?這可以使用表單身份驗證完成嗎?

我目前正在連接到一個現有的數據庫,我已經使用Sql Server Management Studio創建了這個數據庫,並且已經有一個登錄的方法來設置FormsAuthentication,並且這種方式很好用,因爲我可以將authorize屬性添加到我的學校後臺控制器,用於停止要求登錄學校的網頁,除非學校已經登錄。問題是我怎樣才能使這個更具體,以便只有學校登錄才能看到這個區域,而不是管理員成員誰擁有,因爲他們本來還設置FormsAuthentication登錄。

我已經做了很多谷歌搜索,但沒有找到任何具體的問題,因此這篇文章。

如果需要,我可以生成代碼,並且不要求有人爲我寫代碼,而是如何解決這種安全模型的理論解釋。

在此先感謝您的幫助。

public role GetRoleForUser(string sUserName) 
{ 
    // Should only ever have one role... 
    role Role = (from roles in DBModel.roles 
       join userrole in DBModel.user_role on roles.role_id equals userrole.role_id 
       join users in DBModel.users on userrole.user_id equals users.user_id 
       where users.username == sUserName 
       select roles).FirstOrDefault(); 

    return Role; 
} 

使用自定義角色提供

賬戶控制器代碼(現在一個兩個管理員和學校)

[HttpPost] 
public ActionResult LogOn(LogOn model, string returnUrl) 
{ 
    if (ModelState.IsValid) 
    { 
     if (Membership.ValidateUser(model.UserName, model.Password)) 
     { 
      FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe); 
      if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") 
       && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\")) 
      { 
       return Redirect(returnUrl); 
      } 
      else 
      { 
       // Now it's our job to route the user to the correct place. Ask our DB Helper to tell 
       // us what kind of user they are and route accordingly. 
       string sPage = "Index"; 
       string sController = "Home"; 

       var Role = DBHelperFunctions.Instance().GetRoleForUser(model.UserName); 

       switch (Role.role_name) 
       { 
        case LanguageSchoolsConstants.m_RoleAdministrator: 
         { 
          sController = "AuthorisedAdmin"; 
         } 
         break; 
        case LanguageSchoolsConstants.m_RoleSchool: 
         { 
          sController = "AuthorisedSchool"; 
         } 
         break; 
       } 

       return RedirectToAction(sPage, sController); 
      } 
     } 
     else 
     { 
      ModelState.AddModelError("", "The user name or password provided is incorrect."); 
     } 
    } 
在上述方法中使用的

DB輔助函數工作方案

Web.config更改以允許調用角色提供程序:

使用授權
<roleManager defaultProvider="RoleProvider" enabled="true" cacheRolesInCookie="true"> 
     <providers> 
     <clear /> 
     <add name="RoleProvider" type="namespace.Models.Security.CustomRoleProvider" /> 
     <add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="Entities" applicationName="/" /> 
     <add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" /> 
     </providers> 
    </roleManager> 

我的角色提供

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Security; 

namespace neamsepace.Models.Security 
{ 
    public class CustomRoleProvider : RoleProvider 
    { 
     public override void AddUsersToRoles(string[] usernames, string[] roleNames) 
     { 
      throw new NotImplementedException(); 
     } 

     public override string ApplicationName 
     { 
      get 
      { 
       throw new NotImplementedException(); 
      } 
      set 
      { 
       throw new NotImplementedException(); 
      } 
     } 

     public override void CreateRole(string roleName) 
     { 
      throw new NotImplementedException(); 
     } 

     public override bool DeleteRole(string roleName, bool throwOnPopulatedRole) 
     { 
      throw new NotImplementedException(); 
     } 

     public override string[] FindUsersInRole(string roleName, string usernameToMatch) 
     { 
      throw new NotImplementedException(); 
     } 

     public override string[] GetAllRoles() 
     { 
      throw new NotImplementedException(); 
     } 

     public override string[] GetRolesForUser(string username) 
     { 
      using (DB db = new DB()) 
      { 
       string[] RolesForUser = null; 

       user User = db.users.FirstOrDefault(u => u.username.Equals(username, StringComparison.CurrentCultureIgnoreCase) || 
                 u.email.Equals(username, StringComparison.CurrentCultureIgnoreCase)); 

       var roles = from dbroles in db.roles 
          join userroles in db.user_role on dbroles.role_id equals userroles.role_id 
          join users in db.users on userroles.user_id equals users.user_id 
          where users.user_id == User.user_id 
          select dbroles.role_name; 

       if (roles != null) 
       { 
        RolesForUser = roles.ToArray(); 
       } 
       else 
       { 
        RolesForUser = new string[] { }; 
       } 

       return RolesForUser; 

      } 
     } 

     public override string[] GetUsersInRole(string roleName) 
     { 
      throw new NotImplementedException(); 
     } 

     public override bool IsUserInRole(string username, string roleName) 
     { 
      using (DB db = new DB()) 
      { 
       bool bUserInRole = false; 

       user User = db.users.FirstOrDefault(u => u.username.Equals(username, StringComparison.CurrentCultureIgnoreCase) || 
                 u.email.Equals(username, StringComparison.CurrentCultureIgnoreCase)); 

       var roles = from dbroles in db.roles 
          join userroles in db.user_role on dbroles.role_id equals userroles.role_id 
          join users in db.users on userroles.user_id equals users.user_id 
          where users.user_id == User.user_id 
          select dbroles.role_name; 

       if (User != null) 
       { 
        bUserInRole = roles.Any(r => r.Equals(roleName, StringComparison.CurrentCultureIgnoreCase)); 
       } 

       return bUserInRole; 
      } 
     } 

     public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames) 
     { 
      throw new NotImplementedException(); 
     } 

     public override bool RoleExists(string roleName) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
} 

控制器。

[Authorize(Roles = LanguageSchoolsConstants.m_RoleAdministrator)] 
public class AuthorisedAdminController : Controller 
{ 
    // 
    // GET: /AuthorisedAdmin/ 

    public ActionResult Index() 
    { 
     return View(); 
    } 

} 

我真的希望這可以幫助任何人,請隨時發表評論!

感謝您的幫助。

+0

我看到'Membership.ValidateUser'這意味着你正在使用會員供應商。你在使用什麼提供商?更重要的是,您目前如何管理您的用戶(即學生,教授)? – 2013-02-25 11:50:44

+0

我已經創建了自己的MembershipProvidor繼承。我稱它爲SchoolMembershipProvider,我將發佈它包含的代碼。我還有一個從MembershipUser繼承的SchoolMembershipUser。我還會發布上面的代碼。我希望這有助於說明我目前正在做的事情。謝謝。 – Yos 2013-02-25 12:04:31

+0

如果您覺得自定義成員資格提供者編碼感覺舒適,那麼我會建議您實施自定義角色提供者。這個想法基本上是一樣的;你編碼它,把它掛在你的'web.config'中,就是這樣。所有角色檢查將針對您的自定義提供者返回的角色執行。 – 2013-02-25 12:12:27

回答

1

你不需要多個連接字符串(除非你有多個數據塊。)你可以完成你輕鬆地需要通過什麼用[Authorize(Roles = "XYZ")]屬性裝飾你的行動,並定義角色來指定要保護什麼,除了在此內容角色意味着任務。例如:

public class ProfessorsController : Controller 
{ 
    [Authorize(Roles = "Professors.List")] 
    public ViewResult Index() 
    { 
     // TODO: List professors 
    } 

    [Authorize(Roles = "Professors.Create")] 
    public ViewResult Create() 
    { 
     // TODO: Create professor 
    } 

    [Authorize(Roles = "Professors.Update")] 
    public ViewResult Update(int id) 
    { 
     // TODO: Update professor 
    } 

    [Authorize(Roles = "Professors.Delete")] 
    public ViewResult Delete(int id) 
    { 
     // TODO: Delete professor 
    } 
} 

然後,例如,用戶凡Driessen的(教授)將被授予訪問所有四個動作,而用戶比維斯(學生)將被授予只是Professors.List訪問。

+0

謝謝你的回覆。在這種情況下,我可以問教授角色來自哪裏?它是否是數據庫中的角色,即服務器角色?這是否也意味着你沒有多個登錄?連接字符串如何與此相關?非常抱歉,如果我是愚蠢的。 – Yos 2013-02-25 11:11:22

+0

@Yos我覺得你很困惑的事情。服務器角色特定於SQL Server安全性(如授權*到您的數據庫*)。除非您爲應用程序的不同用戶使用不同的SQL登錄(幾乎不適用於Web應用程序),您可以使用單個SQL登錄名和單個連接字符串。理想情況下,在這種情況下,您的角色來自數據庫,以便您可以更改用戶的訪問權限,而無需重新編譯應用程序。 – 2013-02-25 11:18:31

+0

如果您使用一些代碼更新您的問題以查看您的登錄操作是什麼樣的,我可以通過一個示例來更新我的答案,例如如何連接東西以從數據庫中檢索您的角色。 – 2013-02-25 11:22:50

1

您可以在您查看這樣

<%,如果(轉換登錄accessin會話和 您的物品存放的「如果」語句中。的ToString(計算機[ 「准入」])== 「學校」)

{ %> 
   //your controls here 
<% } %> 

如果條件不滿足,它裏面的內容將不會被顯示。

希望這會有所幫助! 此致敬禮。

+0

對不起,「>」干擾了blockquotes。必須編輯幾次:| – c0dem0nkey 2013-02-25 09:53:05

+0

謝謝你的評論。我最終可能會這樣做,因爲這是我在php中製作CMS時所做的。你的意思是,如果用戶登錄到學校部分,則基本上設置訪問權限,如果登錄到管理員部分,則設置管理員訪問權限。那麼簡單地檢查每個視圖中的字符串值?這可以在控制器中完成嗎?我希望通過檢查數據庫角色或登錄來使用授權來解決它。非常感謝您的回覆! – Yos 2013-02-25 11:14:17

+1

是的,它可以在控制器中完成,但仍然需要使用一些viewdata來在控制器和視圖之間傳遞值。有很多方法可以做到這一點。 theres ajax如果你想異步功能,並且它將適合你的邏輯。如果您找到更簡單更好的方法,請與我們分享。祝你好運! – c0dem0nkey 2013-02-25 13:29:18