次の方法に沿って何かを使用して、2 つの MVC サイト (SiteA と SiteB と呼びます) で動作する基本的なシングル サインオンがあります。
http://forums.asp.net/p/1023838/2614630.aspx
それらは同じドメインのサブドメインにあり、web.config でハッシュ\暗号化キーなどを共有します。同じドメインのすべてのサイトからアクセスできるように、Cookie を変更しました。これはすべて正常に機能しているようです。
サイトは別々のサーバー上にあり、同じ SQL データベースにアクセスできないため、実際にユーザー ログインの詳細を保持しているのは SiteA だけです。SiteB にはメンバーシップ データベースがありますが、ユーザーは空です。
これは、次の必要なシナリオでうまく機能します。
1) ユーザーが SiteA にログインする
2) アプリケーションは、SiteA (AJAX による) および SiteB (JSONP を使用した AJAX による) からデータをロードします。
「魔法」が起こる場所である SiteA の AccountController に、次の LogOn アクションがあります。
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
FormsService.SignIn(model.UserName, model.RememberMe);
//modify the Domain attribute of the cookie to the second level of domain
// Add roles
string[] roles = Roles.GetRolesForUser(model.UserName);
HttpCookie cookie = FormsAuthentication.GetAuthCookie(User.Identity.Name, false);
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
// Store roles inside the Forms cookie.
FormsAuthenticationTicket newticket = new FormsAuthenticationTicket(ticket.Version, model.UserName,
ticket.IssueDate, ticket.Expiration, ticket.IsPersistent, String.Join("|", roles), ticket.CookiePath);
cookie.Value = FormsAuthentication.Encrypt(newticket);
cookie.HttpOnly = false;
cookie.Domain = ConfigurationManager.AppSettings["Level2DomainName"];
Response.Cookies.Remove(cookie.Name);
Response.AppendCookie(cookie);
if (!String.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
これは、最初のシナリオでは厳密には必要ないいくつかのことを行いますが、私の質問に関連しています。これは、SiteA にログインするユーザーのロール リストを認証チケットの UserData に挿入します。これは、global.asax で次のように SiteB に「復元」されます。
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
if (Context.Request.IsAuthenticated)
{
FormsIdentity ident = (FormsIdentity) Context.User.Identity;
string[] arrRoles = ident.Ticket.UserData.Split(new[] {'|'});
Context.User = new System.Security.Principal.GenericPrincipal(ident, arrRoles);
}
}
ロールをミックスに追加するまで、上記のすべてが機能します。[Authorize] 属性を使用して SiteB の Controllers\Actions のみを装飾すると、問題なく動作します。しかし、 [Authorize(roles="TestAdmin")] を追加するとすぐに、ユーザーはそのコントローラー アクションにアクセスできなくなります。明らかに、ユーザーを TestAdmin ロールに追加しました。
SiteB で global.asax コードをデバッグすると、global.asax コードをそのままにして問題ないように見えますが、コントローラー自体でブレークポイントにヒットすると、Controller.User と Controller.HttpContext.User は System.ロールが設定されていない Web.Security.RolePrincipal。
私の質問は次のとおりです。SiteB でロールを復元する方法や、これを行う別の方法を知っている人はいますか?