MembershipProvider and RequiresQuestionAndAnswer
We provide a website template for our customers to use as the basis of their websites. Our website has a custom membership provider.
We have had a problem raised by one customer. The customer sends out invitations to prospective members by email with a url to login the member. During registration they set their security question / answer.
However sometimes the prospective member loses the email (and therefore their password) but still tries to join the site.
The customer requested that the member be allowed to reset their password without the usual security question / answer when registration was not complete.
Unfortunately the MembershipProvider doesn't provide the username when requesting whether the question / answer are required. However it does call GetUser() just before.
To get this feature working I added a method (StartingPasswordRecovery) to my MembershipProvider to flag that password reset was active, calling it from the OnVerifyingUser event in the PasswordRecovery page.
While this code works I'm not convinced that it's very robust.
Can anyone point me towards a better solution.
Here's the relevant code I added to my membership provider.
Private _hasUserDefinedQuestionAndAnswer As Boolean
Private _isResettingPassword As Boolean
Public Overloads Overrides 开发者_开发知识库Function GetUser(ByVal username As String, ByVal userIsOnline As Boolean) As System.Web.Security.MembershipUser
...
_hasUserDefinedQuestionAndAnswer = ...
...
End Function
Public Overrides ReadOnly Property RequiresQuestionAndAnswer() As Boolean
Get
If Me._isResettingPassword Then
Me._isResettingPassword = False
Return Me.pRequiresQuestionAndAnswer And Me._hasUserDefinedQuestionAndAnswer
End If
Return Me.pRequiresQuestionAndAnswer
End Get
End Property
Public Sub StartingPasswordRecovery()
Me._isResettingPassword = True
End Sub
I'm not sure if i've understood you correctly, but couldn't you use the User-Profile to determine if a user requires question and answer or not?
web.config:
<profile defaultProvider="YourProfileProvider">
<providers>
<clear/>
<add name="YourProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ConnectionStringToDB" applicationName="/YourApp"></add>
</providers>
<properties>
<add name="RequiresQuestionAndAnswer" defaultValue="false" />
</properties>
</profile>
Custom membership-provider:
Public Overrides ReadOnly Property RequiresQuestionAndAnswer As Boolean
Get
If HttpContext.Current.User.Identity.IsAuthenticated Then
Dim userRequiresQuestionAndAnswer = _
CType(HttpContext.Current.Profile.GetPropertyValue("RequiresQuestionAndAnswer"), Boolean)
Return userRequiresQuestionAndAnswer
Else
Return MyBase.RequiresQuestionAndAnswer
End If
End Get
End Property
You could set it in your user-management page for every user individually:
HttpContext.Current.Profile.SetPropertyValue("RequiresQuestionAndAnswer", userRequiresQuestionAndAnswer)
HttpContext.Current.Profile.Save()
Edit:
according to your comment, i've modified the code a little bit. I hope that helps to get it working:
in custom membership-provider:
Public Overloads Overrides ReadOnly Property RequiresQuestionAndAnswer As Boolean
Get
If HttpContext.Current.User.Identity.IsAuthenticated Then
Return RequiresQuestionAndAnswer(Membership.GetUser.UserName)
Else
Return MyBase.RequiresQuestionAndAnswer
End If
End Get
End Property
Public Overloads ReadOnly Property RequiresQuestionAndAnswer(ByVal userName As String) As Boolean
Get
Dim profile As ProfileBase = ProfileBase.Create(userName)
If Not profile Is Nothing Then
Dim userRequiresQuestionAndAnswer = _
CType(profile.GetPropertyValue("RequiresQuestionAndAnswer"), Boolean)
Return userRequiresQuestionAndAnswer
Else
Return MyBase.RequiresQuestionAndAnswer
End If
End Get
End Property
where your PasswordRecovery-Control is:
Protected Sub VerifyingUser(ByVal sender As Object, ByVal e As LoginCancelEventArgs)
Dim login As WebControls.Login = DirectCast(Me.LoginView1.FindControl("Login1"), WebControls.Login)
Dim userName = DirectCast(login.FindControl("PwdRecovery"), PasswordRecovery).UserName
Dim RequiresQuestionAndAnswer = DirectCast(Membership.Provider, YourMembershipProvider).RequiresQuestionAndAnswer(userName)
'....'
End Sub
精彩评论