2015-07-20 63 views
0

我正在構建一個基於Intranet的應用程序,如下所示,並需要有關管理用戶角色的最佳方法的建議。使用Windows身份驗證管理mvc 5中角色的最佳方法

  1. MVC 5 Windows身份驗證Intranet應用程序。
  2. 不能使用廣告角色將需要與應用程序管理。
  3. 只有3個角色,管理員,主管,將在應用程序中維護的用戶。
  4. 能夠添加/刪除用戶到角色
  5. 將使用AD來獲取用戶名和電子郵件,然後在應用程序內堅持。
  6. 我使用實體框架6和SQL Server(這不會改變)

我不確定創建自己的自定義的方法來管理角色反對使用asp.net身份的方法或任何其他方法。

我在想,因爲它是一個相對簡單的應用程序,我可能只是利用我自己的方法?

+0

這裏有一個很好的概述。 http://www.typecastexception.com/post/2014/04/20/ASPNET-MVC-and-Identity-20-Understanding-the-Basics.aspx#The-Heart-of-it-All---ApplicationDbContext –

+0

好的,謝謝史蒂夫我會通讀這個 – Pod

回答

1

嗯,

這是工作,但如果是我,我會使用Windows Identity Foundation(WIF 4.5)。我將創建一個自定義安全令牌服務和安全令牌配置類。

第一張:

在EF中構建兩個名爲Roles和UsersInRoles的表。

角色

  1. 角色ID(自動遞增)
  2. 作用(VARCHAR(255))

用戶在角色

  1. 用戶名(VARCHAR(255),唯一,主鍵)
  2. 角色ID(外鍵角色 - >角色ID)

的Wif:

第1步:

建設登錄網站,一個新的空MVC網站創建單獨的項目。配置web.config以使用NTLM進行身份驗證並刪除其匿名訪問。給它一個像login.mysite.com這樣的網址。

創建STS,STS配置和CertificateUtil:

public class XYZSecurityTokenServiceConfiguration : SecurityTokenServiceConfiguration 
{ 
    static readonly object syncRoot = new object(); 
    static string stsKey = "XYZSecurityTokenServiceConfiguration"; 


    public static XYZSecurityTokenServiceConfiguration Current 
    { 
     get 
     { 
      HttpApplicationState httpAppState = HttpContext.Current.Application; 
      XYZSecurityTokenServiceConfiguration myConfiguration = httpAppState.Get(stsKey) as XYZSecurityTokenServiceConfiguration; 
      if (myConfiguration != null) 
      { 
       return myConfiguration; 
      } 
      lock (syncRoot) 
      { 
       myConfiguration = httpAppState.Get(stsKey) as XYZSecurityTokenServiceConfiguration; 
       if (myConfiguration == null) 
       { 
        myConfiguration = new XYZSecurityTokenServiceConfiguration(); 
        httpAppState.Add(stsKey, myConfiguration); 
       } 
       return myConfiguration; 
      } 
     } 
    } 

    public XYZSecurityTokenServiceConfiguration() : base("XYZPassiveSTS", CertificateUtil.SigningCreds) 
    { 
     this.SecurityTokenService = typeof(TLCSecurityTokenService); 
    } 
} 


public class XYZSecurityTokenService : SecurityTokenService 
{ 
    public XYZSecurityTokenService(SecurityTokenServiceConfiguration configuration) 
     : base(configuration) 
    {       
    } 

    void ValidateAppliesTo(EndpointReference appliesTo) 
    { 
     if (appliesTo == null) 
     { 
      throw new ArgumentNullException("appliesTo"); 
     } 
    } 

    protected override Scope GetScope(ClaimsPrincipal principal, RequestSecurityToken request) 
    { 
     ValidateAppliesTo(request.AppliesTo); 

     Scope scope = new Scope(
      request.AppliesTo.Uri.OriginalString, 
      SecurityTokenServiceConfiguration.SigningCredentials); 
     scope.TokenEncryptionRequired = false; 

     scope.ReplyToAddress = scope.AppliesToAddress; 
     //scope.ReplyToAddress = request.ReplyTo; 

     return scope; 
    } 

    protected override ClaimsIdentity GetOutputClaimsIdentity(ClaimsPrincipal principal, RequestSecurityToken request, Scope scope) 
    { 
     //We Can Add Additonal Claims Here! 
     ClaimsIdentity claims = new ClaimsIdentity(); 
     claims.AddClaims(principal.Claims); 
     string userName = principal.Identity.Name; 

     //Use EF To get user's roles by userName, 

     var roles = DBContext.GetRolesForUser(userName); 
     foreach (var role in roles) 
     { 
      Claim roleClaim = new Claim(ClaimTypes.Role, role.Role, ClaimValueTypes.String); 
      claims.AddClaims(roleClaim); 
     } 
    } 
} 

public class CertificateUtil 
{ 
    #region Fields 
    private const string SIGNING_CERTIFICATE_NAME = "CN=TokenSigningCert"; 
    private const string ENCRYPTING_CERTIFICATE_NAME = "CN=TokenSigningCert"; 
    private static SigningCredentials _signingCreds = null; 
    private static EncryptingCredentials _encryptingCreds = null; 
    #endregion 

    #region Properties 
    public static SigningCredentials SigningCreds 
    { 
     get 
     { 
      if (_signingCreds == null) 
       _signingCreds = new X509SigningCredentials(CertificateUtil.GetCertificate(StoreName.TrustedPeople, StoreLocation.LocalMachine, SIGNING_CERTIFICATE_NAME)); 
      return _signingCreds; 
     } 
    } 
    public static EncryptingCredentials EncryptingCreds 
    { 
     get 
     { 
      if (_encryptingCreds == null) 
       _encryptingCreds = new X509EncryptingCredentials(CertificateUtil.GetCertificate(StoreName.TrustedPeople, StoreLocation.LocalMachine, ENCRYPTING_CERTIFICATE_NAME)); 
      return _encryptingCreds; 
     } 
    } 

    #endregion 

    /// <summary> 
    /// Get the certificate from a specific store/location/subject. 
    /// </summary> 
    private static X509Certificate2 GetCertificate(StoreName name, StoreLocation location, string subjectName) 
    { 
     X509Store store = new X509Store(name, location); 
     X509Certificate2Collection certificates = null; 
     store.Open(OpenFlags.ReadOnly); 

     try 
     { 
      X509Certificate2 result = null; 

      // 
      // Every time we call store.Certificates property, a new collection will be returned. 
      // 
      certificates = store.Certificates; 

      for (int i = 0; i < certificates.Count; i++) 
      { 
       X509Certificate2 cert = certificates[i]; 

       if (cert.SubjectName.Name.ToLower() == subjectName.ToLower()) 
       { 
        if (result != null) 
        { 
         throw new ApplicationException(string.Format("More than one certificate was found for subject Name {0}", subjectName)); 
        } 

        result = new X509Certificate2(cert); 
       } 
      } 

      if (result == null) 
      { 
       throw new ApplicationException(string.Format("No certificate was found for subject Name {0}", subjectName)); 
      } 

      return result; 
     } 
     finally 
     { 
      if (certificates != null) 
      { 
       for (int i = 0; i < certificates.Count; i++) 
       { 
        X509Certificate2 cert = certificates[i]; 
        cert.Reset(); 
       } 
      } 

      store.Close(); 
     } 
    } 
} 

在登錄網站時,您還需要一個控制器來處理登錄和註銷。現在

,您將使用NTLM,因此該網站的任何請求將被驗證,如果關閉了匿名訪問,他們無法獲得該網站沒有使用NTLM登錄。

因此您的控制器只需做處理請求,

if (!Request.IsAuthenticated) 
    return RedirectToAction("SomethingBroke"); 

CasPrincipal cp = User as CasPrincipal; 
ClaimsPrincipal p = new ClaimsPrincipal(cp.Identity); 
       FederatedPassiveSecurityTokenServiceOperations.ProcessRequest(System.Web.HttpContext.Current.Request, p, WIF.TLCSecurityTokenServiceConfiguration.Current.CreateSecurityTokenService(), System.Web.HttpContext.Current.Response); 

WIF通過查詢字符串參數驅動,不同的參數控制哪些程序請求呢。如果查詢具有wssignin參數,則它將登錄並重定向回主站點。如果它發出警告,它會註銷並重新導回。

現在回到你的主站點,添加web.cofnig條目依賴於WIF登錄網站,

<configuration> 
    <configSections> 
    <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" /> 
    <section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" /> 
    </configSections> 
    <system.webServer> 
    <modules> 
     <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> 
     <add name="WSFederatedAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> 
    </modules> 
    </system.webServer> 
    <system.identityModel> 
    <identityConfiguration saveBootstrapContext="true"> 
     <issuerNameRegistry type="System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
     <trustedIssuers> 
      <!-- Use MMC and the Certificate Snapin to get the thumbprint for your certificate. It will be different on other machines and this value might not work as is from source control.--> 
      <add thumbprint="97f983a05587253b6835d1bd0062000c5d1f398d" name="TokenSigningCert" /> 
     </trustedIssuers> 
     </issuerNameRegistry> 
     <audienceUris mode="Never" /> 
    </identityConfiguration> 
    </system.identityModel> 
    <system.identityModel.services> 
    <federationConfiguration identityConfigurationName=""> 
     <serviceCertificate> 
     <certificateReference x509FindType="FindBySubjectName" findValue="TokenSigningCert" storeLocation="LocalMachine" storeName="TrustedPeople" /> 
     </serviceCertificate> 
     <wsFederation passiveRedirectEnabled="true" issuer="http://login.example.com" realm="http://example.com" requireHttps="false" /> 
     <cookieHandler requireSsl="false" mode="Default"> 
     <chunkedCookieHandler chunkSize="2000" /> 
     </cookieHandler> 
    </federationConfiguration> 
    </system.identityModel.services> 
</configuration> 

最後,在你的主網站,您需要一個控制器來處理登錄和註銷。

你做到這一點與

   //To Log In 
      FederatedAuthentication.WSFederationAuthenticationModule.RedirectToIdentityProvider("MYSiteIDYouMakeUpHere", "TheUrlToReturnToAfterLoginHere", true); 

      //ToLogOut 
      var issuer = FederatedAuthentication.FederationConfiguration.WsFederationConfiguration.Issuer; 
      var signOutUrl = WSFederationAuthenticationModule.GetFederationPassiveSignOutUrl(issuer, "returnurlhere", null); 
      Redirect(signOutUrl); 
+0

對不起,這個答案只有一半完成,沒有時間,但這確實顯示瞭如何從你的應用程序獲取角色並在登錄過程中將它們作爲聲明發布。 –

+0

HI Ryios感謝您的回覆。是的,我會消化這一點。用戶不需要登錄,但它是一個Intranet應用程序。 – Pod

+0

那麼,他們仍然登錄,它可能會無縫地發生。你仍然可以在登錄網站上做到這一點,他們只是不會看到它,它會發生很快。 –

相關問題