如果你忘记了DotnetNuke站点的host和admin密码,解决方案
如果你忘记了DotnetNuke站点的host和admin密码,解决方案?? 没有密码?怎么办
上SQL server, 进去了直奔dbo.aspnet_Membership, 密码是带salt和DNN自己另设的密文加密的, 我头脑一热加手一抖直接把admin和host的密码和salt删了, 然后想用其它站数据库里的密码和salt复制过来, 结果没用, 然后又用hash generator 做了数个加密后的密文+ salt 复制过去, 依然无效. 然后突然想起来, DNN的加密机制不太一样, 每个DNN站的web.config里自己有个独特的密文, 不同站的不一样, 这一下直接不能上了. 这回事情比原来还严重了, 不仅密码忘了, 原来的密码也没了, salt也没了. -.-|||
OK, 事已至此, 咱上google上找一下先吧, 别自己再乱搞了. 搜索一下, 还真找出不少方案来. 后来才知道, 这些方案在我目前的情况下都不适用, 不过那是后话, 我先把这些解决办法列出来, 方便一下看这篇文章的人.
方案一
这个理论上适用于所有情况(但是实际上是痴人说梦..)
- 在你DNN网站上注册一个新用户. 如果你的注册按钮被你在站点设置里关掉了, 那就去SQL server上把dbo.Portals表里的UserRegistration值改成2.
- 用你开的registration建个新用户(把密码记住.. -.-|||)
- 再进数据库, 找到dbo.ASPNet_Membership表
- 到你新建的那个用户那一行中把password, passwordsalt的密文都复制到你的host用户那一行的同样列中(host是superuser).
- 重新用你的host和你新设用户的密码登录DNN然后再把你新建的那个用户删掉就可以了.
很不幸的是, 我的DNN网站的出于当初开发时的安全考虑被我关闭了, 而且他所说的改UserRegistration值的方法是无效的, 改过后Register依然没有在login module中出现.
方案二
这个是需要你已经知道一个帐号的用户名和密码, 然后用下面的SQL query实现对host的密码的替换.
1 2 3 4 5 |
SELECT password, passwordformat, passwordsalt FROM aspnet_membership am INNER JOIN aspnet_users auON (au.userid = am.userid) INNER JOIN aspnet_applications aaON (au.applicationId = aa.applicationid)WHERE au.username = 'admin' AND aa.applicationname = 'DotNetNuke' |
然后把你得到的password, passwordformat, passwordsalt复制到一个地方, 下面的query中从’TestUser’那行开始, 分别对应 用户名, password, passwordsalt, ChangeTime, passwordFormat. 所以你用你刚复制下来的替换下面这几个就可以了.
1 2 3 4 5 6 7 8 9 |
DECLARE @changeDate datetime SET @changeDate = getdate() --set the password exec aspnet_Membership_setPassword 'DotNetNuke', 'TestUser', 'DM1tZvBjM+27Eck5eI1TWFeG42XuJnMuin3jqFOtMjS83RN6d7dFbQ==', '4e5Bb5jOOMYu/JFXVdRmlA==', @changeDate, 2 |
那么很不幸的, 这个方案也是无效的因为我根本没有任何一个知道密码的帐号.而且据我所知DNN 4.4.1以后的版本也不再使用Application ID了, 而是使用Application Name. 所以这里也需要做些小修改才能生效.
方案三
在SQL server 运行这个query
1 2 3 4 5 6 7 8 9 10 11 12 |
Declare @UserName NVarChar(255) Declare @NewPassword NVarChar(255) Declare @PasswordSalt NVarChar(128) Declare @Application NVarChar(255) -- 在下面的单引号间输入你要做的修改(用户名, 密码) -- 别留任何空格除非你特意要留.. SET @UserName = 'admin' -- 这个是DNN默认的admin用户, 这里我们要改成host SET @NewPassword = 'newpassword' -- 这里是你的新密码 SET @Application = (SELECT [ApplicationID] FROM aspnet_Users WHERE UserName=@UserName) SET @PasswordSalt = (SELECT PasswordSalt FROM aspnet_Membership WHERE UserID IN (SELECT UserID FROM aspnet_Users WHERE UserName=@UserName)) Exec dbo.aspnet_Membership_ResetPassword @Application, @UserName, @NewPassword, 10, 10, @PasswordSalt, -5 |
根据这个query来看, 这也是一个DNN 4.4.1以前的方案,但是我做了小量修改, 依然不能在新版本的DNN上有任何效果. 因为他是基于你没有删SALT的基础上的, 而很不幸, 我把密码+SALT都删没了. 失败.
方案四
这个是一个老外的query, 无数老外跟着comment了说好用, 但是很不幸, 他的原理是跟方案一相同的, 也需要你有一个已知密码的帐号, 只不过用query的形式完成了.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
DECLARE @databaseName VARCHAR(128) SELECT @databaseName = DB_NAME() PRINT 'RESET PASSWORD IN DATABASE : ' + @databaseName PRINT '-----------------------------' + REPLICATE('-', DATALENGTH(@databaseName )); DECLARE @knownUserName NVARCHAR(128) DECLARE @lostUserName NVARCHAR(128) DECLARE @lostUserId NVARCHAR(128) DECLARE @knownPassword NVARCHAR(128) DECLARE @knownSalt NVARCHAR(128) SET @knownUserName = 'Tonic' SET @lostUserName = 'host' SELECT @knownPassword = Password, @knownSalt = PasswordSalt FROM aspnet_Membership INNER JOIN aspnet_users ON aspnet_Membership.UserId = aspnet_users.UserId WHERE UserName = @knownUserName; PRINT '' PRINT 'Known Password for "' + @knownUserName + '" is : ' + @knownPassword PRINT 'Known Password Salt for "' + @knownUserName + '" is : ' + @knownSalt SELECT @lostUserId = aspnet_Membership.UserId FROM aspnet_Membership INNER JOIN aspnet_users ON aspnet_Membership.UserId = aspnet_users.UserId WHERE UserName = @lostUserName; PRINT '' PRINT 'UserID for "' + @lostUserName + '" is : ' + @lostUserId PRINT '' IF (DATALENGTH(@lostUserName) <= 0 OR @lostUserName IS NULL) PRINT 'Invalid Lost User Name ' + @lostUserName ELSE BEGIN IF (DATALENGTH(@knownUserName) <= 0 OR @knownUserName IS NULL) PRINT 'Invalid Lost User Name ' + @lostUserName ELSE BEGIN IF (DATALENGTH(@knownPassword) <= 0 OR @knownPassword IS NULL) PRINT 'Invalid Known Password ' + @knownPassword ELSE BEGIN IF (DATALENGTH(@knownSalt) <= 0 OR @knownSalt IS NULL) PRINT 'Invalid Known Salt ' + @knownSalt ELSE BEGIN PRINT '' PRINT 'BEFORE' SELECT LEFT(UserName, 12) AS UserName, aspnet_Membership.UserId, LEFT(Email, 20) AS Email, Password, PasswordSalt FROM aspnet_Membership INNER JOIN aspnet_users ON aspnet_Membership.UserId = aspnet_users.UserId WHERE UserName IN ( @knownUserName, @lostUserName ); PRINT '' PRINT 'Changing Password for User Id : "' + @lostUserId + '" to "' + @knownPassword + '"' PRINT '' UPDATE aspnet_Membership SET Password = @knownPassword, PasswordSalt = @knownSalt -- SELECT UserId, Password, PasswordSalt -- FROM aspnet_Membership WHERE UserId = @lostUserId; PRINT '' PRINT 'AFTER' SELECT LEFT(UserName, 12) AS UserName, aspnet_Membership.UserId, LEFT(Email, 20) AS Email, Password, PasswordSalt FROM aspnet_Membership INNER JOIN aspnet_users ON aspnet_Membership.UserId = aspnet_users.UserId WHERE UserName IN ( @knownUserName, @lostUserName ); END END END END GO PRINT '' PRINT ' * * * END OF SCRIPT * * *' PRINT '' GO |
显然, 前面已经提过, 我没有一个现成的知道密码的帐号, 所以再次失败.
方案五
由于我之前的失败都因为没有一个可以工作的而且知道密码的帐号, 而又不能在网站上注册新帐号, 于是我找到了一个方法可以用SQL创建一个新帐号.
query如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
SELECT m.password, m.passwordsalt, m.passwordformat FROM aspnet_users u INNER JOIN aspnet_membership m ON (u.userid = m.userid) WHERE u.UserName = 'TestUser' SELECT PortalId, PortalName FROM Portals DECLARE @ApplicationName nvarchar(256) SET @ApplicationName = 'DotNetNuke' DECLARE @UserName nvarchar(256) SET @UserName = 'NewUser' --The new user DECLARE @Password nvarchar(128) --From the existing user SET @Password = 'LLSXX8xW6+0EbrV4JBzL/YenA1D6BBfRnkYY7FtQvNGmmPOhVdPiAA==' DECLARE @PasswordSalt nvarchar(128) --From the existing user SET @PasswordSalt = 'P40ky5tExsx37nUIFnCWZQ==' DECLARE @Email nvarchar(256) SET @Email = 'TestingAccount@test.com' --You can set this to whatever you want DECLARE @PasswordQuestion nvarchar(256) SET @PasswordQuestion = '' DECLARE @PasswordAnswer nvarchar(128) SET @PasswordAnswer = '' DECLARE @IsApproved bit SET @IsApproved = 1 DECLARE @CurrentTimeUtc datetime SET @CurrentTimeUtc = GETDATE() DECLARE @CreateDate datetime SET @CreateDate = @CurrentTimeUtc DECLARE @UniqueEmail int SET @UniqueEmail = 0 DECLARE @PasswordFormat int SET @PasswordFormat = 2 --NOTE: Value from existing user! DECLARE @PortalId int SET @PortalId = 0 --The id of your portal Declare @UserId uniqueidentifier DECLARE @DNNUserId int --Make the stored procedure call EXEC dbo.aspnet_Membership_CreateUser @ApplicationName, @Username, @Password, @PasswordSalt, @email, @passwordquestion, @PasswordAnswer, @IsApproved, @CurrentTimeUtc, @CreateDate, @UniqueEmail, @PasswordFormat, @UserId --Insert the record into the DotNetNuke users table INSERT INTO users (Username, FirstName, LastName, IsSuperUser, Email, DisplayName, UpdatePassword) VALUES(@Username, 'My', 'NewAccount', 0, @Email, 'New Account', 0) --Get the new userid, from the DNN users table SELECT @dnnuserid = userid FROM Users WHERE username = @Username --Now, insert the record into the user portals table INSERT INTO UserPortals (userId, PortalId, CreatedDate) VALUES(@dnnuserid, @PortalId, GETDATE()) --Now Give the user permissions to the RECISTERED Users group INSERT INTO UserRoles (userId, roleId) SELECT @dnnuserid, roleId FROM Roles WHERE RoleName = 'Registered Users' |
然而我不得不再次不幸的告诉大家, 从这个query来看, 要使用这个query建立一个DNN新用户, 也是需要事先有一个知道密码, salt, applicationname的帐户才可以的, 可悲的是我的密码和salt密文已经被我完全删干净了. 再次失败.
成功方案
经过了这数次失败以后, 我终于放弃google了, 看来这次真的无法找到我要的答案, 既然数据库方向我无法找到结果, 那么只能从代码上动手脚了, 不就是想注册新用户么, 我开始找login module的code.
DNN的这个目录下存放着login module的代码, 打开后开始查找对portal setting里Userregistration属性的判定, 经过一翻查找和测试, 总算找到了, Page_Load里面的这一段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
If Not Request.IsAuthenticated Then If Page.IsPostBack = False Then Try If Not Request.QueryString("username") Is Nothing Then txtUsername.Text = Request.QueryString("username") End If If Not Request.QueryString("verificationcode") Is Nothing Then If PortalSettings.UserRegistration = PortalRegistrationType.VerifiedRegistration Then ' Comment this line above and the "End If" below out if you can't login as admin or host ' and can't change the register setting in SQL and don't even have an password-known account ' and really really desperatly want to register a new user. -- Kang 10.07.2008 'Display Verification Rows rowVerification1.Visible = True rowVerification2.Visible = True txtVerification.Text = Request.QueryString("verificationcode") End If End If Catch 'control not there End Try End If |
这段代码中的comment是我加的.. (当时实在很无语), 判定网站是否开放注册的部分就是其中If PortalSettings.UserRegistration = PortalRegistrationType.VerifiedRegistration Then 和下面的End IF这两行, 我把他们前面加个’ 给comment掉再重新编译运行网站, register就出来了, 之后我把自己新注册的用户在数据库中的superuser设成true(dbo.Users表里面), 然后用这个帐号登录DNN, 把host和admin的salt随便写一个在数据库里加上, 再把他俩的密码reset, 然后重新change password为我想要的, 大功告成. 本来也可以用上面几个方案中给出的换密码的办法, 不过看了这么久的query我实在不想再弄了, 直接去万恶的DNN后台里改了.
希望对跟我一样犯了愚蠢错误的DNN开发人员有所帮助.
真的很长啊, 谢谢观赏 本文来自:http://www.k4ng.com/archives/244
http://www.blog-design.cn