Azure - 實作Azure上的AD與MVC進行驗證 - Azure設定篇 ( 三 )
持續努力,現在進入第三篇了!!,第三篇我們先以完成為目標,所以小弟先不在這邊講Code的內容了,這部份未來再補上。
TenantDbContext.cs的內容為:
using System;
using System.Data.Entity;
namespace WebApplication2.Models
{
public class TenantDbContext : DbContext
{
public TenantDbContext()
: base("DefaultConnection")
{
}
public DbSet<IssuingAuthorityKey> IssuingAuthorityKeys { get; set; }
public DbSet<Tenant> Tenants { get; set; }
}
}
TenantRegistrationModels.cs的內容為:
using System;
using System.Collections.Generic;
using System.Linq;
namespace WebApplication2.Models
{
public class IssuingAuthorityKey
{
public string Id { get; set; }
}
public class Tenant
{
public string Id { get; set; }
}
}
接著,我們要建立一個Utils的目錄,然後建立一個DatabaseIssuerNameRegistry.cs檔案。
DatabaseIssuerNameRegistry.cs的內容為:
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Web;
using System.Web.Hosting;
using System.Xml.Linq;
using WebApplication2.Models;
namespace WebApplication2.Utils
{
public class DatabaseIssuerNameRegistry : ValidatingIssuerNameRegistry
{
public static bool ContainsTenant(string tenantId)
{
using (TenantDbContext context = new TenantDbContext())
{
return context.Tenants
.Where(tenant => tenant.Id == tenantId)
.Any();
}
}
public static bool ContainsKey(string thumbprint)
{
using (TenantDbContext context = new TenantDbContext())
{
return context.IssuingAuthorityKeys
.Where(key => key.Id == thumbprint)
.Any();
}
}
public static void RefreshKeys(string metadataLocation)
{
IssuingAuthority issuingAuthority = ValidatingIssuerNameRegistry.GetIssuingAuthority(metadataLocation);
bool newKeys = false;
bool refreshTenant = false;
foreach (string thumbprint in issuingAuthority.Thumbprints)
{
if (!ContainsKey(thumbprint))
{
newKeys = true;
refreshTenant = true;
break;
}
}
foreach (string issuer in issuingAuthority.Issuers)
{
if (!ContainsTenant(GetIssuerId(issuer)))
{
refreshTenant = true;
break;
}
}
if (newKeys || refreshTenant)
{
using (TenantDbContext context = new TenantDbContext())
{
if (newKeys)
{
context.IssuingAuthorityKeys.RemoveRange(context.IssuingAuthorityKeys);
foreach (string thumbprint in issuingAuthority.Thumbprints)
{
context.IssuingAuthorityKeys.Add(new IssuingAuthorityKey { Id = thumbprint });
}
}
if (refreshTenant)
{
foreach (string issuer in issuingAuthority.Issuers)
{
string issuerId = GetIssuerId(issuer);
if (!ContainsTenant(issuerId))
{
context.Tenants.Add(new Tenant { Id = issuerId });
}
}
}
context.SaveChanges();
}
}
}
private static string GetIssuerId(string issuer)
{
return issuer.TrimEnd('/').Split('/').Last();
}
protected override bool IsThumbprintValid(string thumbprint, string issuer)
{
return ContainsTenant(GetIssuerId(issuer))
&& ContainsKey(thumbprint);
}
}
}
接下來,我們要在App_Start底下新增IdentityConfig.cs檔案。
IdentityConfig.cs的內容為:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IdentityModel.Claims;
using System.IdentityModel.Services;
using System.Linq;
using System.Web.Helpers;
using WebApplication2.Utils;
namespace WebApplication2
{
// 如需 ASP.NET Identity 的詳細資訊,請造訪 http://go.microsoft.com/fwlink/?LinkId=301863
public static class IdentityConfig
{
public static string AudienceUri { get; private set; }
public static string Realm { get; private set; }
public static void ConfigureIdentity()
{
RefreshValidationSettings();
// 設定應用程式領域
Realm = ConfigurationManager.AppSettings["ida:realm"];
// 設定應用程式 audienceUri
AudienceUri = ConfigurationManager.AppSettings["ida:AudienceUri"];
if (!String.IsNullOrEmpty(AudienceUri))
{
UpdateAudienceUri();
}
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Name;
}
public static void RefreshValidationSettings()
{
string metadataLocation = ConfigurationManager.AppSettings["ida:FederationMetadataLocation"];
DatabaseIssuerNameRegistry.RefreshKeys(metadataLocation);
}
public static void UpdateAudienceUri()
{
int count = FederatedAuthentication.FederationConfiguration.IdentityConfiguration
.AudienceRestriction.AllowedAudienceUris.Count(
uri => String.Equals(uri.OriginalString, AudienceUri, StringComparison.OrdinalIgnoreCase));
if (count == 0)
{
FederatedAuthentication.FederationConfiguration.IdentityConfiguration
.AudienceRestriction.AllowedAudienceUris.Add(new Uri(IdentityConfig.AudienceUri));
}
}
}
}
接下來,我們要在Global.asax裡面加入註冊使用上面的IdentityConfig。
加入IdentityConfig.ConfigureIdentity();
void Application_Start(object sender, EventArgs e)
{
// 應用程式啟動時執行的程式碼
AreaRegistration.RegisterAllAreas();
IdentityConfig.ConfigureIdentity();
GlobalConfiguration.Configure(WebApiConfig.Register);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
最後,我們有用到DB,所以還是要補一下連線字串;這邊小弟我是使用LocalDB,大家也可以建立自己想要的DB位置。
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-WebApplication1-20140901114034.mdf;Initial Catalog=aspnet-WebApplication1-20140901114034;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
完成之後,你會發現,使用HTTPS時,就會要求先使用Azure來登入帳號了~~
以上!!