2010-03-03 4 views
7

Wie gebe ich eine Zeichenfolgenachricht von der ValidateUser-Methode in meinem benutzerdefinierten Mitgliedschaftsanbieter zurück? Ich brauche das, weil ich mehrere Überprüfungen durchführen möchte (Benutzer ist genehmigt, Benutzer ist blockiert usw.) und gebe dem Benutzer eine gute Beschreibung, wenn der Anmeldevorgang fehlschlägt.ASP.NET MVC 2 - Mitgliedschaftsanbieter - ValidateUser() - Anmeldefehlermeldung zurückgeben

Eine Option wäre, eine Ausnahme auszulösen, aber jemand sagte, dass dies keine geeignete Methode sei, um solche Situationen zu bewältigen.

Momentan kann ich nur sagen "Login fehlgeschlagen" oder "Login erfolgreich" wegen der bool Rückgabetyp.

Ist es möglich, meine eigene ValidateUser-Methode zu erstellen, oder verwendet der ASP.NET-Mitgliedschaftsmechanismus den Standard in seinen internen Operationen?

+1

Es ist keine gute Idee, eine Aussperrung auf einer Web-basierte Anwendung zu berichten, jemand eine Brute-Force-Attacke versucht, wissen eher zu stoppen und zu warten, als die Ausübung und möglicherweise das richtige Passwort präsentieren zu ein gesperrtes Konto und damit keinen Zugang. Nur ein Gedanke für dich. – Lazarus

+0

Danke für diesen Hinweis Lazarus. – Cosmo

+2

Dies ist ein Mangel des MembershipProvider. ValidateUser() gibt nur ein Bool zurück, was Sie mit BAD-Optionen belässt. 1) requery die Datenbank für weitere Informationen (Overhead), 2) Methoden hinzufügen und Ihren Provider (die Unabhängigkeit brechen), oder 3) eine Out-of-Band-Cookie-Operation. MS sollte den Anbieter aktualisieren. Es wäre großartig, wenn ValidateUser mindestens zurückliefert und AuthenticationStatuts enumeriert, ähnlich wie CreateUser() eine MembershipCreateStatus-Enumeration zurückgibt. Obwohl ich etwas mehr sehen möchte, da selbst die MembershipCreateStatus-Enumeration begrenzt ist (http://forums.asp.net/t/1521981.aspx). – EBarr

Antwort

2

Das sind zwei verschiedene Operationen.

Um zu sehen, ob ein Benutzer zugelassen ist, gesperrt, etc., um die Benutzer sehen (mit GetUser()) und Blick auf den IsApproved, IsLockedOut usw. Eigenschaften des zurückgegebenen Benutzers. ValidateUser() ist nur für die Anmeldung, aber Sie können beides tun.

+0

Danke Craig. Also meinst du, ich sollte zuerst den Benutzer validieren (Benutzername, Passwort), dann, wenn der Datensatz existiert, überprüfe, ob der Benutzer ausgesperrt ist, genehmigt etc. und dann den Authentifizierungs-Cookie gesetzt habe? Habe ich recht? Zweite Frage. Ich verwende ein benutzerdefiniertes RegUser-Objekt (nicht MembershipUser). Sollte ich separate Methoden in meinem Mitgliedschaftsanbieter wie GetRegUser erstellen, um meine benutzerdefinierten Attribute zu überprüfen? – Cosmo

+0

Ich denke, ich würde "MembershipUser" Subtype, anstatt sie zu ersetzen, aber bevor Sie tun, beachten Sie (1) gibt es bereits eine Eigenschaft für App-spezifische Daten http://msdn.microsoft.com/en-us/library/ system.web.security.membershipuser.comment.aspx und (2) App-spezifische Benutzerinformationen sind oft besser für IIdentity geeignet als für einen Mitgliedschaftsbenutzer. Mitgliedschaftsbenutzer sagen wirklich nur, ob Sie hineinkommen können. IIdentity sagt * wer Sie sind. * –

+0

Oh, und das ist wahrscheinlich offensichtlich, aber Sie müssen nur den Benutzer nachschlagen, wenn Login fehlschlägt. Wenn es gelingt, müssen sie genehmigt werden und können nicht ausgesperrt werden. –

0

Sie müssten Ihren eigenen Mechanismus erstellen; Dies geschieht standardmäßig nicht und kann nicht mit dem integrierten Mitgliedschaftsanbieter durchgeführt werden. Du könntest diesen Provider einpacken und diese Methode hinzufügen und das selbst machen ... das ist eine Option. Aber das funktioniert nicht im Einklang mit dem Login-Steuerelement, wenn Sie es verwenden.

+0

Danke Brian, ich benutze nicht die Login-Kontrolle. Wahrscheinlich wäre das eine Option. – Cosmo

2

Sie können implementieren jeden Methoden, die Sie auf Ihrem benutzerdefinierten Anbieter zu wollen, und in Ihrem Fall es Macht Sinn so und nur werfen Mitgliedschaft auf Ihre Art zu tun, bevor Sie.

Aber das Brechen der Schnittstelle, um einige einfache Out-of-Band-Informationen zu bekommen, kann in der Zukunft wieder beißen. Es gibt andere Möglichkeiten, dies zu tun und die Provider-API zu erhalten und Ihre zukünftigen Optionen offen zu halten.

In der Vergangenheit habe ich ein Cookie verwendet, um Out-of-Band-Informationen wie diese von einem Anbieter an den Verbraucher zu übergeben.

Der HttpContext.Current ist für den Anbieter derselbe wie für die Seite, so dass ein Cookie, der in dem Anbieter festgelegt wird, in dem Consumer gelesen werden kann.

Stellen Sie einfach sicher, dass Sie den Cookie nach dem Aufruf Ihres Providers entfernen. Das Erstellen eines temporären Cookies hilft Fehler zu minimieren, aber entfernen Sie es trotzdem aus der Sammlung.

Hier ist ein Arbeitsbeispiel.

CookieChannelMembershipProvider

using System; 
using System.Web; 
using System.Web.Security; 

namespace CookieChannel 
{ 
    public class CookieChannelMembershipProvider : MembershipProvider 
    { 
     public override bool ValidateUser(string username, string password) 
     { 
      if(username=="asshat") 
      { 
       HttpContext.Current.Request.Cookies.Add(new HttpCookie("__cookiechannel", "user is an asshat. do not let him in.")); 
       return false; 
      } 
      return true; 
     } 

     #region Not implemented 

     public override bool EnablePasswordRetrieval 
     { 
      get { throw new NotImplementedException(); } 
     } 

     public override bool EnablePasswordReset 
     { 
      get { throw new NotImplementedException(); } 
     } 

     public override bool RequiresQuestionAndAnswer 
     { 
      get { throw new NotImplementedException(); } 
     } 

     public override string ApplicationName 
     { 
      get { throw new NotImplementedException(); } 
      set { throw new NotImplementedException(); } 
     } 

     public override int MaxInvalidPasswordAttempts 
     { 
      get { throw new NotImplementedException(); } 
     } 

     public override int PasswordAttemptWindow 
     { 
      get { throw new NotImplementedException(); } 
     } 

     public override bool RequiresUniqueEmail 
     { 
      get { throw new NotImplementedException(); } 
     } 

     public override MembershipPasswordFormat PasswordFormat 
     { 
      get { throw new NotImplementedException(); } 
     } 

     public override int MinRequiredPasswordLength 
     { 
      get { throw new NotImplementedException(); } 
     } 

     public override int MinRequiredNonAlphanumericCharacters 
     { 
      get { throw new NotImplementedException(); } 
     } 

     public override string PasswordStrengthRegularExpression 
     { 
      get { throw new NotImplementedException(); } 
     } 


     public override MembershipUser CreateUser(string username, string password, string email, 
                string passwordQuestion, string passwordAnswer, bool isApproved, 
                object providerUserKey, out MembershipCreateStatus status) 
     { 
      throw new NotImplementedException(); 
     } 

     public override bool ChangePasswordQuestionAndAnswer(string username, string password, 
                  string newPasswordQuestion, string newPasswordAnswer) 
     { 
      throw new NotImplementedException(); 
     } 

     public override string GetPassword(string username, string answer) 
     { 
      throw new NotImplementedException(); 
     } 

     public override bool ChangePassword(string username, string oldPassword, string newPassword) 
     { 
      throw new NotImplementedException(); 
     } 

     public override string ResetPassword(string username, string answer) 
     { 
      throw new NotImplementedException(); 
     } 

     public override void UpdateUser(MembershipUser user) 
     { 
      throw new NotImplementedException(); 
     } 


     public override bool UnlockUser(string userName) 
     { 
      throw new NotImplementedException(); 
     } 

     public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) 
     { 
      throw new NotImplementedException(); 
     } 

     public override MembershipUser GetUser(string username, bool userIsOnline) 
     { 
      throw new NotImplementedException(); 
     } 

     public override string GetUserNameByEmail(string email) 
     { 
      throw new NotImplementedException(); 
     } 

     public override bool DeleteUser(string username, bool deleteAllRelatedData) 
     { 
      throw new NotImplementedException(); 
     } 

     public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords) 
     { 
      throw new NotImplementedException(); 
     } 

     public override int GetNumberOfUsersOnline() 
     { 
      throw new NotImplementedException(); 
     } 

     public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, 
                   out int totalRecords) 
     { 
      throw new NotImplementedException(); 
     } 

     public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, 
                    out int totalRecords) 
     { 
      throw new NotImplementedException(); 
     } 
     #endregion 
    } 
} 

Web.config

<?xml version="1.0"?> 
<configuration> 
    <system.web> 
    <compilation debug="true"/> 
    <authentication mode="Windows" /> 
    <membership defaultProvider="cookieChannelProvider" userIsOnlineTimeWindow="15"> 
     <providers> 
     <add 
      name="cookieChannelProvider" 
      type="CookieChannel.CookieChannelMembershipProvider, CookieChannel" 
      connectionStringName="none" 
      enablePasswordRetrieval="true" 
      enablePasswordReset="true" 
      requiresQuestionAndAnswer="true" 
      /> 
     </providers> 
    </membership> 
    </system.web> 
</configuration> 

Standard.aspx

<%@ Page Language="C#" %> 
<script runat="server"> 
    protected void Button1_Click(object sender, EventArgs e) 
    { 
     ValidateUser("user", "user"); 
    } 
    protected void Button2_Click(object sender, EventArgs e) 
    { 
     ValidateUser("asshat", "asshat"); 
    } 

    private void ValidateUser(string username, string password) 
    { 
     bool validated = Membership.ValidateUser(username, password); 
     string message = validated.ToString(); 

     if (Request.Cookies["__cookiechannel"] != null) 
     { 
      message += ":" + Request.Cookies["__cookiechannel"].Value; 
      Request.Cookies.Remove("__cookiechannel"); 
     } 
     Label1.Text = message; 
    } 
</script> 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

<html xmlns="http://www.w3.org/1999/xhtml" > 
<head runat="server"> 
    <title></title> 
</head> 
<body> 
    <form id="form1" runat="server"> 
    <div> 

     <asp:Button ID="Button1" runat="server" onclick="Button1_Click" 
      Text="Validate Valued User" /> 
     <asp:Button ID="Button2" runat="server" onclick="Button2_Click" 
      Text="Validate Asshat User" /> 

    </div> 
    <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label> 
    </form> 
</body> 
</html>