如果你忘记了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