2010-03-30 20 views
17

tôi thực hiện một đối tượng tùy chỉnh hồ sơ trong mã như mô tả của Joel đây:Sử dụng ASP .NET Membership và Profile với MVC, làm thế nào tôi có thể tạo một người dùng và đặt nó thành HttpContext.Current.User?

How to assign Profile values?

tôi không thể làm cho nó hoạt động khi tôi đang tạo một người dùng mới, tuy nhiên. Khi tôi làm điều này:

Membership.CreateUser(userName, password); 
Roles.AddUserToRole(userName, "MyRole"); 

người dùng được tạo ra và thêm vào một vai trò trong cơ sở dữ liệu, nhưng HttpContext.Current.User vẫn còn trống rỗng, và Membership.GetUser() lợi nhuận null, vì vậy đây (từ mã của Joel) không hoạt động:

static public AccountProfile CurrentUser 
{ 
    get { return (AccountProfile) 
        (ProfileBase.Create(Membership.GetUser().UserName)); } 
} 

AccountProfile.CurrentUser.FullName = "Snoopy"; 

tôi đã thử gọi Membership.GetUser(userName) và thiết lập các thuộc hồ sơ như vậy, nhưng các thuộc tính thiết lập vẫn trống rỗng, và kêu gọi AccountProfile.CurrentUser(userName).Save() không đặt bất cứ điều gì trong cơ sở dữ liệu. Tôi cũng đã cố gắng cho biết rằng người dùng đã đăng nhập & hợp lệ, bằng cách gọi Membership.ValidateUser, FormsAuthentication.SetAuthCookie, v.v. nhưng người dùng hiện tại vẫn không có hoặc ẩn danh (tùy thuộc vào trạng thái cookie của trình duyệt của tôi).

GIẢI PHÁP (CHỈNH SỬA THÊM, XEM DƯỚI): Dựa trên lời giải thích của Franci Penov và một số thử nghiệm khác, tôi đã tìm ra vấn đề. Mã của Joel và các biến thể mà tôi đã thử sẽ chỉ hoạt động với Cấu hình hiện có. Nếu không có Tiểu sử nào tồn tại, ProfileBase.Create(userName) sẽ trả về một đối tượng trống mới mỗi khi được gọi; bạn có thể thiết lập các thuộc tính, nhưng chúng sẽ không "dính" vì một cá thể mới được trả về mỗi lần bạn truy cập nó. Đặt HttpContext.Current.User thành GenericPrincipalmới sẽ cung cấp cho bạn đối tượng Người dùng, nhưng không đối tượng Tiểu sử và ProfileBase.Create(userName)HttpContext.Current.Profile sẽ vẫn trỏ đến đối tượng mới, trống.

Nếu bạn muốn tạo Hồ sơ cho Người dùng mới được tạo trong cùng một yêu cầu, bạn cần gọi HttpContext.Current.Profile.Initialize(userName, true). Sau đó, bạn có thể điền tiểu sử được khởi tạo và lưu nó, và nó sẽ có thể truy cập được trên các yêu cầu trong tương lai theo tên, do đó mã của Joel sẽ hoạt động. Tôi chỉ chỉ sử dụng HttpContext.Current.Profile nội bộ, khi tôi cần tạo/truy cập vào Tiểu sử ngay khi tạo. Trên bất kỳ yêu cầu nào khác, tôi sử dụng ProfileBase.Create(userName) và tôi đã chỉ hiển thị phiên bản đó là công khai. Lưu ý rằng Franci là chính xác: Nếu bạn sẵn sàng tạo User (và Vai trò) và đặt nó là Authenticated trên chuyến đi khứ hồi đầu tiên, và yêu cầu người dùng đăng nhập, bạn sẽ có thể truy cập vào Hồ sơ nhiều hơn nữa chỉ đơn giản là thông qua mã của Joel về yêu cầu tiếp theo. Điều gì đã ném tôi là Roles có thể truy cập ngay lập tức khi người dùng tạo mà không có bất kỳ khởi tạo nào, nhưng Hồ sơ thì không.

đang AccountProfile mới của tôi:

public static AccountProfile CurrentUser 
{ 
    get 
    { 
     if (Membership.GetUser() != null) 
      return ProfileBase.Create(Membership.GetUser().UserName) as AccountProfile; 
     else 
      return null; 
    } 
} 

internal static AccountProfile NewUser 
{ 
    get { return System.Web.HttpContext.Current.Profile as AccountProfile; } 
} 

tạo người dùng mới:

MembershipUser user = Membership.CreateUser(userName, password); 
Roles.AddUserToRole(userName, "MyBasicUserRole"); 
AccountProfile.NewUser.Initialize(userName, true); 
AccountProfile.NewUser.FullName = "Snoopy"; 
AccountProfile.NewUser.Save(); 

truy cập tiếp theo:

if (Membership.ValidateUser(userName, password)) 
{ 
    string name = AccountProfile.CurrentUser.FullName; 
} 

nhờ Hơn nữa để Franci cho giải thích vòng đời xác thực - Tôi m gọi FormsAuthentication.SetAuthCookie trong chức năng xác nhận của tôi, nhưng tôi trả lại một bo ol để cho biết thành công, vì User.Identity.IsAuthenticated sẽ không đúng cho đến khi yêu cầu tiếp theo.

ĐƯỢC SỬA ĐỔI: Tôi là kẻ ngốc. Lời giải thích ở trên hoạt động trong trường hợp hẹp, nhưng không giải quyết được vấn đề cốt lõi: Gọi CurrentUser trả về một cá thể mới của đối tượng mỗi lần, cho dù đó là một Profile hiện có hay không. Bởi vì nó được định nghĩa là một tài sản, tôi đã không nghĩ về điều này, và đã viết:

AccountProfile.CurrentUser.FullName = "Snoopy"; 
AccountProfile.CurrentUser.OtherProperty = "ABC"; 
AccountProfile.CurrentUser.Save(); 

mà (tất nhiên) không hoạt động. Nó phải là:

AccountProfile currentProfile = AccountProfile.CurrentUser; 
currentProfile.FullName = "Snoopy"; 
currentProfile.OtherProperty = "ABC"; 
currentProfile.Save(); 

Đó là lỗi của riêng tôi để xem hoàn toàn điểm cơ bản này, nhưng tôi cho rằng CurrentUser là một thuộc tính ngụ ý rằng đó là một đối tượng có thể được thao tác. Thay vào đó, nó phải được khai báo là GetCurrentUser().

Trả lời

7

Tạo người dùng chỉ cần thêm nó vào danh sách người dùng. Tuy nhiên, điều này không xác thực hoặc ủy quyền cho người dùng mới cho yêu cầu hiện tại. Bạn cũng cần phải xác thực người dùng trong ngữ cảnh yêu cầu hiện tại hoặc cho các yêu cầu tiếp theo.

Membership.ValidateUser sẽ chỉ xác thực thông tin đăng nhập, nhưng nó không xác thực người dùng cho các yêu cầu hiện tại hoặc tiếp theo. FormsAuthentication.SetAuthCookie sẽ đặt vé xác thực trong luồng phản hồi, vì vậy yêu cầu tiếp theo sẽ được xác thực, nhưng nó không ảnh hưởng đến trạng thái của yêu cầu hiện tại.

Cách dễ nhất để xác thực người dùng sẽ gọi số FormsAuthentication.RedirectFromLoginPage (giả sử bạn đang sử dụng xác thực biểu mẫu trong ứng dụng của mình). Tuy nhiên, điều này thực sự sẽ gây ra một yêu cầu HTTP mới, điều này sẽ xác thực người dùng. Ngoài ra, nếu bạn cần tiếp tục logic của mình để xử lý yêu cầu hiện tại, nhưng muốn người dùng được xác thực, bạn có thể tạo GenericPrincipal, chỉ định danh tính của người dùng mới và đặt HttpContext.User cho hiệu trưởng đó.

+0

Sẽ làm việc này mạo danh người dùng khác không? –

+0

Mạo danh thường ngụ ý xác thực Windows, yêu cầu WindowsPrincipal. Mạo danh có thể được thực hiện từ mã thông báo bảo mật cho người dùng mạo danh hoặc từ thông tin đăng nhập. Do bối cảnh hiện tại không được xác thực, rất có thể không có cách nào để nhận mã thông báo bảo mật cho người dùng. Do đó, các lựa chọn duy nhất là mạo danh bằng thông tin đăng nhập. Nó có thể có thể xây dựng một WindowsPrincipal với danh tính thích hợp bằng cách gọi LogonUser (cung cấp mã biết thông tin đăng nhập cho người dùng windows). Tuy nhiên, tôi đã không cố gắng này, vì vậy tôi không thể xác minh nó sẽ nhất thiết phải làm việc. –

+0

Đó là một lời giải thích cực kỳ hữu ích, cảm ơn bạn.Tạo một GenericPrincipal (từ FormsAuthenticationTicket của tôi) đã cho phép tôi đặt HttpContext.Current.User. Tuy nhiên, tôi vẫn không thể đặt giá trị Hồ sơ. Nếu tôi sử dụng ProfileBase.Create (Membership.GetUser(). UserName) .SetPropertyValue, không có gì xảy ra - nó không ném một ngoại lệ nữa, nhưng thuộc tính vẫn trống. Nếu tôi sử dụng HttpContext.Current.Profile.SetPropertyValue, nó nói rằng tôi không thể thiết lập thuộc tính trên một hồ sơ vô danh, ngụ ý rằng đây là những đối tượng Profile khác nhau mà tôi bằng cách nào đó cần phải hợp nhất. –

0

Trước hết, cảm ơn @Jeremy vì đã chia sẻ những phát hiện của bạn. Bạn đã giúp tôi đi đúng hướng. Thứ hai, xin lỗi vì đã chạm vào bài đăng cũ này. Hy vọng rằng điều này sẽ giúp ai đó kết nối các dấu chấm.

Cách cuối cùng tôi đã làm việc này là sử dụng phương pháp tĩnh sau bên trong lớp hồ sơ của tôi:

internal static void InitializeNewMerchant(string username, Merchant merchant) 
{ 
    var profile = System.Web.HttpContext.Current.Profile as MerchantProfile; 
    profile.Initialize(username, true); 
    profile.MerchantId = merchant.MerchantId; 
    profile.Save(); 
} 
1

Bạn sẽ gặp vấn đề với phương pháp này nếu bạn kích hoạt anonymousIdentification. Thay vì Membership.GetUser(). UserName, tôi sẽ đề nghị sử dụng HttpContext.Profile.UserName.

Như thế này ...

private UserProfile _profile; 
private UserProfile Profile 
{ 
    get { return _profile ?? (_profile = (UserProfile)ProfileBase.Create(HttpContext.Profile.UserName)); } 
} 

Hat tip: SqlProfileProvider - can you use Profile.GetProfile() in a project?

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