Verwenden von ASP .NET Mitgliedschaft und Profil mit MVC, wie kann ich einen Benutzer erstellen und setzen Sie ihn auf HttpContext.Current.User?

StackOverflow https://stackoverflow.com/questions/2547290

Frage

Ich implementiert ein benutzerdefinierten Profile Objekt in Code wie hier von Joel beschrieben:

Wie Profilwerte zuweisen?

Ich kann es nicht zur Arbeit, wenn ich einen neuen Benutzer bin zu schaffen, aber. Wenn ich dies tun:

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

der Benutzer erstellt wird und auf eine Rolle in der Datenbank hinzugefügt, aber HttpContext.Current.User noch leer ist, und Membership.GetUser() kehrt null, so dass diese (von Joel-Code) nicht funktioniert:

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

AccountProfile.CurrentUser.FullName = "Snoopy";

Ich habe versucht Aufruf Membership.GetUser(userName) und Einstellung Profileigenschaften auf diese Weise, aber die eingestellten Eigenschaften bleiben leer, und AccountProfile.CurrentUser(userName).Save() Aufruf nichts in der Datenbank setzen. Ich habe auch versucht, das anzeigt, dass der Benutzer gültig ist und angemeldet, durch den Aufruf Membership.ValidateUser, FormsAuthentication.SetAuthCookie, etc., aber der aktuelle Benutzer ist immer noch null oder anonym (in Abhängigkeit vom Zustand meines Browser Cookies).

GELÖST (Edited WEITERE, siehe unten): Basierend auf Franci Penov Erklärung und einige mehr Experimente, dachte ich, das Problem aus. Joels Code und die Variationen habe ich versucht, nur mit einem vorhandenen Profil arbeiten. Wenn kein Profil vorhanden ist, wird ProfileBase.Create(userName) ein neues leeres Objekt zurück jedes Mal, es heißt; Sie können Eigenschaften festgelegt, aber sie werden nicht „kleben“, weil eine neue Instanz jedes Mal, wenn Sie darauf zugreifen zurückgegeben. Einstellen HttpContext.Current.User zu einem neuen GenericPrincipal wird geben Sie ein Benutzerobjekt, aber nicht ein Profilobjekt, und ProfileBase.Create(userName) und HttpContext.Current.Profile noch zeigen neue, leere Objekte.

Wenn Sie ein Profil für einen neu erstellten Benutzer in der gleichen Anforderung erstellen möchten, müssen Sie Anruf HttpContext.Current.Profile.Initialize(userName, true). Sie können dann das initialisierte Profil bevölkern und speichern, und es wird auf zukünftige Anfragen nach Namen zugänglich sein, so Joel Code arbeiten. Ich bin nur mit HttpContext.Current.Profile intern, wenn ich erstellen müssen / Zugang für Profil unmittelbar nach der Erstellung. Auf alle anderen Anfragen, ich benutze ProfileBase.Create(userName), und ich habe nur diese Version als Öffentlichkeit ausgesetzt.

Beachten Sie, dass Franci ist richtig: Wenn Sie bereit sind, den Benutzer (und Rollen) zu erstellen und als authentifizieren auf dem ersten Round-Trip gesetzt, und bitten Sie den Benutzer dann anmelden, werden Sie in der Lage sein, das Profil zugreifen viel einfacher über Joels Code auf der anschließenden Anfrage. Was mich geworfen ist, dass die Rollen bei der Erstellung eines Benutzers ohne Initialisierung unmittelbar zugänglich ist, aber Profil nicht.

Mein neuer AccountProfile Code:

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

Neue Benutzererstellung:

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

Im Anschluss Zugang:

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

Weitere dank Franci zur Erläuterung des Authentifizierungslebenszyklus - Ich rufe FormsAuthentication.SetAuthCookie in meiner Validierungsfunktion, aber ich bin ein Bool Rückkehr Erfolg anzuzeigen, weil User.Identity.IsAuthenticated nicht wahr sein, bis die nachfolgenden Anfrage.

revised: Ich bin ein Idiot. Die obige Erklärung arbeitet im engen Fall, aber löst nicht das Kernproblem: Aufruf Current eine neue Instanz des Objekts gibt jedes Mal, ob es sich um ein vorhandenes Profil oder nicht. Weil es als eine Eigenschaft definiert ist, war ich nicht darüber nachgedacht, und schrieb:

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

, die (natürlich) nicht funktioniert. Es sollte sein:

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

Es ist meine eigene Schuld für völlig diesen grundlegenden Punkt mit Blick auf, aber ich glaube erklärt Current als eine Eigenschaft impliziert, dass es ein Objekt, das manipuliert werden kann. Stattdessen sollte es als GetCurrentUser() deklariert werden.

War es hilfreich?

Lösung

Erstellen eines Benutzers kommt noch hinzu, um es in die Liste der Benutzer. Allerdings bedeutet dies nicht authentifizieren oder die neuen Benutzer für die aktuelle Anforderung genehmigen. Sie müssen auch die Benutzer in dem aktuellen Anforderungskontext authentifizieren oder für nachfolgende Anfragen.

Membership.ValidateUser wird nur die Anmeldeinformationen validieren, aber es ist nicht der Benutzer für den aktuellen oder nachfolgenden Anforderungen zu authentifizieren. FormsAuthentication.SetAuthCookie das Authentifizierungsticket in der Antwortstream gesetzt, so dass die nächste Anforderung, authentifiziert werden, aber es nicht den Zustand der aktuellen Anforderung beeinflussen.

Der einfachste Weg, um den Benutzer zu authentifizieren würde Anruf FormsAuthentication.RedirectFromLoginPage sein (vorausgesetzt, Sie verwenden Formularauthentifizierung in Ihrer Anwendung). Dies würde jedoch eine tatsächlich eine neue HTTP-Anforderung verursachen, die den Benutzer authentifizieren.

Alternativ, wenn Sie benötigen, um Ihre Logik weiterhin für Verarbeiten der aktuellen Anforderung, sondern wollen, dass der Benutzer authentifiziert werden, können Sie eine GenericPrincipal erstellen können, weisen sie die Identität des neuen Benutzers und stellen Sie die HttpContext.User zu diesem Haupt.

Andere Tipps

Sie werden zu laufen Probleme mit diesem Ansatz, wenn Sie anonymousIdentification ermöglichen. Anstatt Membership.GetUser (). Username, würde ich vorschlagen HttpContext.Profile.UserName verwenden.

Wie dies ...

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

Hat tip: SqlProfileProvider - können Sie Profile.GetProfile verwenden () in einem Projekt?

Vor allem dank @ Jeremy für Ihre Erkenntnisse zu teilen. Sie hat mir geholfen, in die richtige Richtung gehen würde. Zweitens, sorry für diese alte Post stoßen. Hoffentlich wird jemand helfen die Punkte verbinden.

Die Art und Weise habe ich endlich diese Arbeit war die folgende statische Methode in meinem Profilklasse zu verwenden:

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();
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top