如何在 SQL 中为 SQLMembershipProvider 添加用户和角色?
我们正在迁移到生产环境,我想编写一个脚本,让 DBA 在运行我使用 aspnet_regsql
生成的脚本后可以立即创建具有角色的用户。在开发环境中,我一直在 Global.asax.cs 中使用成员资格提供商的 API 添加用户和角色。但我想避免这种硬编码方法。现在我的 T-SQL 经验不足已经暴露出来了。我编写了以下脚本,如果我不立即运行它,它就会起作用。
Use MyApps_Prod;
GO
DECLARE @user_identity CHAR(40);
DECLARE @scalar_userid AS NVARCHAR(255);
DECLARE @scalar_roleid AS NVARCHAR(255);
DECLARE @app_id AS NVARCHAR(255);
SET @user_identity = N'AMERICAS\First.Last';
SET @app_id = (SELECT DISTINCT ApplicationId
FROM [dbo].[aspnet_Applications]
WHERE loweredapplicationname = 'MyApplication');
SELECT * FROM [dbo].[aspnet_Users] WHERE UserName = @user_identity
IF NOT EXISTS (SELECT * FROM [dbo].[aspnet_Users] WHERE UserName = @user_identity )
BEGIN
INSERT INTO [dbo].aspnet_Users
( [ApplicationId], [UserName], [LoweredUserName], [LastActivityDate] )
VALUES
( @app_id, @user_identity, LOWER(@user_identity), GETDATE());
END;
DECLARE @role_name CHAR(40);
SET @role_name = N'Communicator';
IF NOT EXISTS (SELECT * FROM [dbo].[aspnet_Roles] WHERE RoleName = @role_name )
BEGIN
INSERT INTO [dbo].[aspnet_Roles]
( [ApplicationId], [RoleName], [LoweredRoleName])
VALUES
(@app_id, @role_name, LOWER(@role_name))
END;
SET @scalar_userid = (SELECT DISTINCT UserID FROM [dbo].aspnet_Users WHERE UserName = @user_identity);
SET @scalar_roleid = (SELECT DISTINCT RoleID FROM [dbo].aspnet_Roles WHERE RoleName = @role_name);
INSERT INTO [dbo].aspnet_UsersInRoles (UserID, RoleID)
VALUES (
@scalar_userid ,
@scalar_roleid
);
SET @role_name = N'AccessAdministrator';
IF NOT EXISTS (SELECT * FROM [dbo].[aspnet_Roles] WHERE RoleName = @role_name )
BEGIN
INSERT INTO [dbo].[aspnet_Roles]
( [ApplicationId], [RoleName], [LoweredRoleName])
VALUES
(@app_id, @role_name, LOWER(@role_name))
END;
SET @scalar_roleid = (SELECT DISTINCT RoleID FROM [dbo].aspnet_Roles WHERE RoleName = @role_name);
INSERT INTO [dbo].aspnet_UsersInRoles (UserID, RoleID)
VALUES (
@scalar_userid ,
@scalar_roleid
);
GO
我发现如果我用分号结束每个 INSERT
然后添加 GO
,我就可以让 INSERTs
工作,但随后我需要重新声明并重新分配每个变量。
真正的 SQL 开发人员会如何做到这一点?
We are migrating to the production environment, and I want to write a sript the the DBA can create a user with the roles immediately after running the script I've generated with aspnet_regsql
. In the Development environment, I have been adding users and roles with the Membership Provider's API in the Global.asax.cs. But I want to avoid this hard-coded approach. Now my T-SQL lack of exprience is showing. I wrote the following script, which works if I don't run it all at once.
Use MyApps_Prod;
GO
DECLARE @user_identity CHAR(40);
DECLARE @scalar_userid AS NVARCHAR(255);
DECLARE @scalar_roleid AS NVARCHAR(255);
DECLARE @app_id AS NVARCHAR(255);
SET @user_identity = N'AMERICAS\First.Last';
SET @app_id = (SELECT DISTINCT ApplicationId
FROM [dbo].[aspnet_Applications]
WHERE loweredapplicationname = 'MyApplication');
SELECT * FROM [dbo].[aspnet_Users] WHERE UserName = @user_identity
IF NOT EXISTS (SELECT * FROM [dbo].[aspnet_Users] WHERE UserName = @user_identity )
BEGIN
INSERT INTO [dbo].aspnet_Users
( [ApplicationId], [UserName], [LoweredUserName], [LastActivityDate] )
VALUES
( @app_id, @user_identity, LOWER(@user_identity), GETDATE());
END;
DECLARE @role_name CHAR(40);
SET @role_name = N'Communicator';
IF NOT EXISTS (SELECT * FROM [dbo].[aspnet_Roles] WHERE RoleName = @role_name )
BEGIN
INSERT INTO [dbo].[aspnet_Roles]
( [ApplicationId], [RoleName], [LoweredRoleName])
VALUES
(@app_id, @role_name, LOWER(@role_name))
END;
SET @scalar_userid = (SELECT DISTINCT UserID FROM [dbo].aspnet_Users WHERE UserName = @user_identity);
SET @scalar_roleid = (SELECT DISTINCT RoleID FROM [dbo].aspnet_Roles WHERE RoleName = @role_name);
INSERT INTO [dbo].aspnet_UsersInRoles (UserID, RoleID)
VALUES (
@scalar_userid ,
@scalar_roleid
);
SET @role_name = N'AccessAdministrator';
IF NOT EXISTS (SELECT * FROM [dbo].[aspnet_Roles] WHERE RoleName = @role_name )
BEGIN
INSERT INTO [dbo].[aspnet_Roles]
( [ApplicationId], [RoleName], [LoweredRoleName])
VALUES
(@app_id, @role_name, LOWER(@role_name))
END;
SET @scalar_roleid = (SELECT DISTINCT RoleID FROM [dbo].aspnet_Roles WHERE RoleName = @role_name);
INSERT INTO [dbo].aspnet_UsersInRoles (UserID, RoleID)
VALUES (
@scalar_userid ,
@scalar_roleid
);
GO
I have found that I can get the INSERTs
to work if I end each INSERT
with a semicolon and then add GO
, but then I need to redeclare and reassign each variable.
How would a real SQL developer do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
不要手动编写 INSERT 语句,而是使用存储过程,这些存储过程是
SqlMembershipProvider
实现提供程序的一部分,并且在使用aspnet_reg.exe
工具安装应用程序服务时包含在内。特别是,使用:
aspnet_Roles_CreateRole
创建新角色aspnet_Membership_CreateUser
来创建用户并提供其成员数据(密码、安全问题和答案等)aspnet_UsersInRoles_AddUsersToRoles
将现有用户添加到现有角色aspnet_Membership_CreateUser
是其中唯一棘手的一个。假设您不是以纯文本形式存储密码,则需要通过@Password
参数将散列或加密版本传递到存储过程中。我建议使用 Reflector 检查 SqlMembershipProvider 类的CreateUser
方法。在那里您将看到 .NET 如何在幕后处理此逻辑。作为编写此脚本的替代方法,请考虑编写一个命令行程序,该程序可能读取文本文件并创建指定的角色和用户以及用户角色关联。该命令行程序将直接使用会员 API,因此将处理所有低级详细信息。然后,您可以执行此命令行程序作为构建或部署过程的一部分。
快乐编程!
Rather than writing INSERT statements by hand, use the stored procedures that are part of the
SqlMembershipProvider
implementation provider and are included when installing application services using theaspnet_reg.exe
tool.In particular, use:
aspnet_Roles_CreateRole
to create a new roleaspnet_Membership_CreateUser
to create a user and supply his membership data (password, security question and answer, and so forth)aspnet_UsersInRoles_AddUsersToRoles
to add an existing user to an existing roleThe
aspnet_Membership_CreateUser
is the only tricky one out of the lot. Presuming you are storing your passwords not in plain-text, you need to pass in either the hashed or encrypted version into the sproc via the@Password
parameter. I suggest using Reflector to examine the code in theSqlMembershipProvider
class'sCreateUser
method. There you will see how .NET handles this logic underneath the covers.As an alternative to scripting this, consider writing a command line program that, perhaps, reads a text file and creates the specified roles and users and user-role associations. This command line program would use the Membership API directly and would, therefore, handle all of the low level details. You could then execute this command line program as part of your build or deployment process.
Happy Programming!
您是否尝试过在运行 SQL Profiler 的情况下运行硬编码实现?这应该会告诉你运行的确切顺序。
Have you tried running your hard-coded implementation with SQL Profiler running? That should show you the exact order to run things.
“真正的 SQL 开发人员会如何做到这一点?”
这是一个开始。
虽然 T-SQL 不直接支持数组,但我通常会循环遍历表变量,将它们视为数组,以压缩/重用代码。在你的例子中,这并不是一个巨大的好处。但是,如果有 10 个角色名,那就是了。
例子:
"How would a real SQL developer do this?"
Here's a start.
While T-SQL does not directly support arrays, I'll typically loop through table variables, treating them as arrays, to condense/reuse code. In your example, it's not a huge benefit. But, if there were 10 rolenames, it would be.
Example:
通过脚本创建它不是一个好主意。另外我不确定你什么时候说如果你使用 API 则必须手动创建。您是否尝试过迁移现有数据?
但如果这是选择,那么我建议您使用 Reflector Tool 来查看这些membership /Roles 方法的代码。仅运行存储过程是不够的,因为在这些 API 方法执行存储过程之前,可能会根据您在 web.config 中的设置进行加密/散列、选择正确的 applicationName 以及其他一些检查。
因此,请确保考虑所有这些,因为您将能够插入用户详细信息,但当您想要使用它时,您将使用 API,这可能会破坏其他内容。
That isn't a good idea creating it via script. Also I am not sure when you say you have to create manually if you are using API. Did you try migrating your existing data?
But if that is the choice then I would suggest you to use Reflector Tool to see the code of those membership /Roles methods. Just running the stored proc isn't sufficient because there might be encryption/hashing, picking right applicationName and several other checks involved as per you setting in the web.config before the stored proc is executed by those API methods.
So make sure you consider all those because you will be be able to insert user details but when you want to use it, you will be use API and that might break something else.