2010-08-30 40 views
8

Tôi có cơ bản Single Sign-On làm việc trên 2 trang web MVC (gọi cho họ Sitea và SiteB) sử dụng một cái gì đó dọc theo dòng của phương pháp sau đây:ASP.NET MVC Single Sign-on và vai trò

http://forums.asp.net/p/1023838/2614630.aspx

Chúng nằm trên các tên miền phụ của cùng một tên miền và chia sẻ các khóa băm \ mã hóa vv trong web.config. Tôi đã sửa đổi cookie để có thể truy cập tất cả các Trang web trên cùng một tên miền. Tất cả điều này dường như được làm việc ok.

Các trang web nằm trên các máy chủ riêng biệt mà không truy cập vào cùng cơ sở dữ liệu SQL, do đó chỉ SiteA thực sự giữ chi tiết đăng nhập của người dùng. SiteB có một cơ sở dữ liệu thành viên, nhưng với người dùng trống.

này hoạt động tốt cho kịch bản được yêu cầu của tôi đó là:

log 1) Ký vào Sitea

2) tải ứng dụng dữ liệu từ Sitea (bằng AJAX) và SiteB (bằng AJAX sử dụng JSONP)

tôi có đăng nhập Action sau trên AccountController tôi cho Sitea, đó là nơi mà các "kỳ diệu" sẽ xảy ra:

[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."); 
     } 
    } 

này làm một số công cụ mà tôi không nghiêm ngặt ly cần cho kịch bản ban đầu, nhưng liên quan đến câu hỏi của tôi. Nó chèn danh sách Vai trò cho người dùng khi đăng nhập vào SiteA vào UserData của vé xác thực. Điều này sau đó được "khôi phục" trên SiteB theo các điều sau trong global.asax:

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); 
    } 
} 

Tất cả các công cụ trên đều hoạt động cho đến khi tôi thêm Vai trò vào hỗn hợp. Mọi thứ hoạt động tốt nếu tôi chỉ trang trí các Controller \ Actions trên SiteB với các thuộc tính [Authorize]. Nhưng ngay sau khi tôi thêm người dùng [Authorize (roles = "TestAdmin")] thì người dùng không còn có thể truy cập vào Hành động điều khiển đó nữa. Rõ ràng là tôi đã thêm người dùng vào vai trò TestAdmin.

Nếu tôi gỡ lỗi mã global.asax trên SiteB, có vẻ như ok khi tôi rời khỏi mã global.asax, NHƯNG sau đó khi tôi nhấn một điểm ngắt trong bộ điều khiển chính nó, Controller.User và Controller.HttpContext.User là bây giờ là System.Web.Security.RolePrincipal không có vai trò nào được đặt nữa.

Vì vậy, câu hỏi của tôi là: Có ai có bất kỳ ý tưởng làm thế nào tôi có thể khôi phục lại vai trò trên SiteB hoặc một cách khác để làm điều này?

Trả lời

2

Bạn đã làm việc nó ra, nhưng ở đây chúng tôi đi:

làm cho nó làm việc: tắt quản lý vai trò. Nó không phải là một hành vi kỳ quặc mà asp.net đang làm điều đó, vì bạn đang rõ ràng nói với nó để sử dụng tìm kiếm vai trò của người dùng với configuration specified.

cách khác để thực hiện: bật trình quản lý vai trò trong cả hai. Sử dụng configuration để chia sẻ cookie như bạn đang thực hiện trong mã tùy chỉnh của mình. Dựa trên mô tả của bạn, bạn không cần lo lắng về việc cố gắng nhận vai trò cho người dùng, miễn là bạn sử dụng cấu hình phù hợp cho cookie xác thực

bạn nên sử dụng Application_AuthorizeRequest để đặt cookie vai trò? ý kiến ​​của imho trước đó (Authenticate) là tốt nhất, tôi đã luôn luôn làm theo cách đó và không bao giờ gặp phải vấn đề.

+0

Cảm ơn. Yeah, hầu hết những gì tôi đã làm, nhưng thật tuyệt khi có xác nhận. :) Tôi sẽ vui vẻ chấp nhận điều này như là câu trả lời nếu bạn có thể đưa ra một số lý do Application_AuthenticateRequest có thể tốt hơn Application_AuthorizeRequest. – mutex

2

Vì điều này dường như đã bị trì trệ nên tôi có thể trả lời một phần câu hỏi này với một số phát hiện bổ sung. Sau khi gỡ lỗi \ thử nghiệm này nhiều hơn một chút, có vẻ như MVC2 đang làm một cái gì đó kỳ lạ sau khi rời khỏi Application_AuthenticateRequest nhưng trước khi vào Controller của tôi. Xem thêm chi tiết ở đây:

http://forums.asp.net/t/1597075.aspx

Một cách giải quyết là sử dụng Application_AuthorizeRequest thay vì Application_AuthenticateRequest.

EDIT: Tôi tin rằng tôi đã tìm ra nguyên nhân gây ra sự cố của mình. Trong dự án MVC1 của tôi, tôi đã vô hiệu hóa roleManager nhưng dự án MVC2 thử nghiệm của tôi đã kích hoạt roleManager. Khi tôi kích hoạt roleManager của mình trong dự án thử nghiệm MVC1, hành vi giữa MVC1 và MVC2 là như nhau. Tôi cũng có một câu hỏi cho một trong những nhóm MVC Microsoft mở về điều này, và sẽ đăng lại ở đây nếu Application_AuthorizeRequest là nơi chính xác để khôi phục các Vai trò từ cookie vé xác thực ...

Các vấn đề liên quan