在旧版 ASP.NET 网站项目中,我应该在哪里定义 MembershipValidatePasswordEventHandler?
Posted
技术标签:
【中文标题】在旧版 ASP.NET 网站项目中,我应该在哪里定义 MembershipValidatePasswordEventHandler?【英文标题】:Where should I define a MembershipValidatePasswordEventHandler in a legacy ASP.NET Website Project? 【发布时间】:2022-01-24 01:38:19 【问题描述】:我正在开发一个使用自定义 MembershipProvider 的旧版 ASP.NET 网站项目。我想利用它提供的现有功能来实现密码验证。我想确保所有未来的密码都具有一定的长度,并且包含一定数量的大写、小写和非字母数字字符。
到目前为止,我所做的是根据文档中的示例here 在网站默认页面的 page_load 函数中注册一个 MembershipValidatePasswordEventHandler。我目前将事件处理程序设置为拒绝所有内容作为概念证明,并且它可以工作。尽管如此,考虑到站点中有多个页面,并且默认页面与密码创建/管理没有任何关系,注册事件处理程序似乎是一个奇怪的地方。
public partial class _Default : System.Web.UI.Page
protected void Page_Load(object sender, EventArgs e)
Membership.ValidatingPassword += new MembershipValidatePasswordEventHandler(ValidatePasswordEventHandler);
...
public void ValidatePasswordEventHandler(object sender, ValidatePasswordEventArgs e)
e.Cancel = true;
我已经考虑在用户创建或更新页面中注册处理程序,但这似乎仍然不合适。我想知道在我开始执行实际密码检查之前是否有更合适的地方来执行此操作,或者这是执行此操作的标准位置?
对于更广泛问题的其他上下文,我还尝试根据 this 先前的答案修改 web.config 文件中的成员资格提供程序以获取此功能的一部分,但是当我提供无效密码时(小于 7个字符)它不会被拒绝。
<membership defaultProvider="MyMembershipProvider" userIsOnlineTimeWindow="15">
<providers>
<add name="MyMembershipProvider" type="MyNamespace.Membership.MyMembershipProvider" applicationName="MyApp" connectionStringName="MyConnectionString" enablePasswordRetrieval="true" enablePasswordReset="true" requiresQuestionAndAnswer="true" writeExceptionsToEventLog="false" passwordFormat="Clear" maxInvalidPasswordAttempts="15" passwordAttemptWindow="10" minRequiredPasswordLength="7"/>
</providers>
</membership>
更新: This 问题还可以为我为什么对 is 事件处理程序感兴趣提供一些额外的理由。最佳答案链接到this 问题。这个问题的最佳答案提到做我在这里所做的事情,但说它可能会“在更高的范围内”完成,这更能解决我的问题。在网站项目的上下文中,更高/最高范围是什么?
解决方案: 我最终使用以下正则表达式修改了我的 ChangePassword Web 控件的 NewPasswordRegularExpression 字段:^(?=.[az])(?=.[AZ])(?=. \d)(?=.[^\da-zA-Z]).8,$,而不是实现自定义事件处理程序。
【问题讨论】:
【参考方案1】:嗯,好的。嗯,登录页面当然是在web.config中指定的。
在那个登录页面上,您很可能使用了 asp.net“登录”控件。这样登录控制就会有成员资格提供者 - 像这样说:
<asp:Login ID="Login1" runat="server" Width="675px" Height="177px"
MembershipProvider="mysqlProvider" UserNameLabelText="Username:"
FailureText="Login attempt was not successful. Please try again." Font-Size="Small"
>
<LayoutTemplate>
<div style="margin-left:10px">
<h>Please enter your Username and Password</h>
<br />
因此,在您的应用程序中的某个位置 - 创建了会员提供程序,并且将(应该)存在于应用程序中。因此,上述登录控件将“使用”并使用该成员资格提供程序类。在那堂课上,会有这样的例行“事情”:
Public Overrides Function ValidateUser(username As String, password As String) As Boolean
Dim rst As DataTable
Dim strSQL As String =
"SELECT * from dbo_ContactName WHERE Email = @user AND PasswordHash = @pass " &
"AND IsWebActive = 1"
Dim cmdSQL As New SqlCommand(strSQL)
cmdSQL.Parameters.Add("@Email", SqlDbType.NVarChar).Value = username
cmdSQL.Parameters.Add("@pass", SqlDbType.NVarChar).Value = password
rst = MyRstP(cmdSQL)
因此,登录页面有一个登录控件 - 但它最终会按照上述方式调用成员资格提供程序“ValidateUser”。
虽然看起来没有“任何”连接,或者指定自定义提供程序如何调用上述验证用户?好吧,登录控件中的标记指定了成员资格提供者 - 这就是两者的联系方式。
在您的登录页面(带有 asp.net 登录控件的页面)中,如果一切顺利,则触发此事件:
Protected Sub Login1_LoggedIn(sender As Object, e As EventArgs) Handles Login1.LoggedIn
' this event raises AFTER the user is authenticated
'
' check if user is first time logon
' this means that user id = email address
etc. etc. - do whatever you want for custom logon code.
我不确定以上是否有帮助,但它至少显示了登录控件和成员资格提供程序如何相互连接。现在,可能从未使用过标准的 asp.net 登录控件 - 在这种情况下,登录控件的事件模型将不会被使用。显示登录控件的属性表,我们看到:
所以登录控件有一组事件 - 但用户的实际验证发生在我假设在这里使用的自定义 sqlmemberShipProivder 类中。因此,该类应该有一大堆东西,比如 GetUser、ValidateUser、ChangePassword。这里的整个想法是当提供程序正确编写时,登录控制的使用、更改密码控制等都将为您工作,而无需为此过程构建工具箱中提供的登录控制。
所以,在那个自定义类 (sqlMemberShipProivder) 中,有这样的: (还有更多)
我没有看到 Validate Password 用户 - 但有一个 ValidateUser 事件。
【讨论】:
好吧,看来我可能会迷失在杂草中,然后通过挖掘内部事件?首要目标是强制执行密码要求,我将开始寻找不同的途径。如果您有任何建议,那么简单地定义一个方法,例如,由 CreateUser、ChangePassword 和 ResetPassword 调用的 MyValidatePassword 是否合理? 密码要求是一个 VAST VAST 不同的问题。您需要找到该自定义 sqlprovider 类。如果不存在,那么您使用内置类和对象。诸如最小密码长度、最大密码长度等内容也将在该类中找到。整个想法是您的自定义提供程序将使用在基类中找到的完全相同的方法。它们匹配,因为最小/最大密码长度、密码复杂性等的配置和设置是在 IIS 配置面板中设置的。您破坏了该对象模型,现在您尝试编写安全系统而不是为此使用 IIS。 是的,很多幕后的地方都会调用并使用验证用户。 IIS 服务将随时调用并使用该方法。 ONE 方法有 ONE 使用和 ONE 单独使用 - 用户 + 密码是否存在 - 是或否?密码长度等是一种 100% 不同的方法 - 与验证方法无关。因此,允许尝试次数、允许格式等方法是不同的方法。第一个也是简单的问题是你在那个项目中找到了 sqlProvider 类吗?如果是,请查看该课程。如果没有,那么您根本没有使用自定义 sqlprovider 但是,您可能没有使用自定义 sql 提供程序这一事实并不能阻止或有必要确定其他事情,例如密码策略等。您使用自定义 sqlprovider 来确保安全的主要原因是您很可能不想使用标准表来确保安全。例如,您可能已经有一些包含客户的应用程序,并且您想使用该客户表来代替为您生成用户表的标准 asp 脚本。因此自定义提供程序允许您使用不同的表来包含用户,而不是默认表。 所以不要混淆自定义 sql 提供程序的问题,而不是说想要更改或拥有一些密码策略 - 在 99% 的情况下,只需添加一些登录代码就可以实现您想要的。正如我所说,您必须首先确定是否在此处创建或使用了自定义登录系统(自定义 sqlprovider)。如果没有,那么您使用内置的提供程序来确保安全 - 这也很好。因此,不要将标准的 asp.net 登录系统和安全系统与想要实现一些密码要求更改的系统混淆。以上是关于在旧版 ASP.NET 网站项目中,我应该在哪里定义 MembershipValidatePasswordEventHandler?的主要内容,如果未能解决你的问题,请参考以下文章
将基于 Angular 6 的网页与旧版 ASP.NET 门户网站合并