2010-12-17 17 views
5

Estamos migrando al entorno de producción y quiero escribir un mensaje para que el administrador de bases de datos pueda crear un usuario con las funciones inmediatamente después de ejecutar el script que he generado con aspnet_regsql. En el entorno de Desarrollo, he agregado usuarios y roles con la API del proveedor de membresía en Global.asax.cs. Pero quiero evitar este enfoque rígido. Ahora se muestra mi falta de experiencia en T-SQL. Escribí el siguiente script, que funciona si no lo ejecuto todo de una vez.Cómo agregar usuarios y roles en SQL para SQLMembershipProvider?

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 

He descubierto que puedo conseguir el INSERTs a trabajar si termino cada INSERT con un punto y coma y luego añadir GO, pero luego tengo que redeclare y reasignar cada variable.

¿Cómo podría un desarrollador real de SQL hacer esto?

+0

Si todo lo demás falla, déjelo en el archivo global.asax para v1 y quítelo para v2. – Greg

Respuesta

10

En lugar de escribir instrucciones INSERT a mano, utilice los procedimientos almacenados que forman parte del proveedor de implementación SqlMembershipProvider y se incluyen al instalar servicios de aplicación utilizando la herramienta aspnet_reg.exe.

En particular, utilice:

  • aspnet_Roles_CreateRole para crear un nuevo papel
  • aspnet_Membership_CreateUser para crear un usuario y suministrar sus datos de afiliación (contraseña, la pregunta y respuesta de seguridad, y así sucesivamente)
  • aspnet_UsersInRoles_AddUsersToRoles para agregar un usuario existente a una función existente

La aspnet_Membership_CreateUser es la única complicada del lote. Suponiendo que está almacenando sus contraseñas no en texto plano, debe pasar la versión codificada o hash en el sproc a través del parámetro @Password.Sugiero usar Reflector para examinar el código en SqlMembershipProvider class CreateUser method. Allí verá cómo .NET maneja esta lógica debajo de las cubiertas.

Como alternativa a la creación de scripts, considere escribir un programa de línea de comandos que, tal vez, lea un archivo de texto y cree los roles y usuarios especificados y asociaciones de roles de usuario. Este programa de línea de comando usaría la API de Membresía directamente y, por lo tanto, manejaría todos los detalles de bajo nivel. Luego puede ejecutar este programa de línea de comando como parte de su proceso de compilación o implementación.

Happy Programming!

+0

Me gusta la sugerencia de línea de comandos. – Greg

+0

Esto funcionó como un encanto. Gracias. – Blanthor

2

¿Ha intentado ejecutar su implementación codificada con SQL Profiler ejecutándose? Eso debería mostrarle el orden exacto para ejecutar las cosas.

+0

Lo intentaré gracias. – Blanthor

+0

Al menos debe usar los procedimientos almacenados incluidos en la base de datos si puede. El generador de perfiles debería mostrarle cómo usarlos. – Greg

+0

+1 Esto fue muy útil gracias. – Blanthor

0

"¿Cómo podría un desarrollador SQL real hacer esto?"

Aquí hay un comienzo. Si bien T-SQL no admite matrices directamente, habitualmente recorreré las variables de la tabla, tratándolas como matrices, para condensar/reutilizar el código. En tu ejemplo, no es un gran beneficio. Pero, si hubiera 10 nombres de rol, sería.

Ejemplo:


DECLARE @roles TABLE (rolename CHAR(40)); 
INSERT @roles 
SELECT 'Communicator' 
UNION ALL 
SELECT 'AccessAdministrator'; 
DECLARE @rolename CHAR(40); 

--loop through the @roles table variable like it's an array 
WHILE (SELECT COUNT(*) FROM @roles) > 0 
    BEGIN 
    SELECT TOP 1 @rolename = rolename FROM @roles; 
    --Do something with the current rolename 
    SELECT @rolename; 
    DELETE @roles WHERE rolename = @rolename; 
    END 
0

Eso no es una buena idea de crearlo a través de la escritura. Además, no estoy seguro de cuándo debe crear manualmente si usa API. ¿Intentó migrar sus datos existentes?

Pero si esa es la opción, le sugiero que utilice la herramienta Reflector para ver el código de esos métodos de membresía/Roles. Simplemente ejecutar el proceso almacenado no es suficiente porque puede haber encriptación/hashing, eligiendo el nombre de aplicación correcto y varias otras verificaciones involucradas según la configuración de usted en el web.config antes de que el método almacenado sea ejecutado por esos métodos API.

Así que asegúrese de tener en cuenta todos estos porque podrá insertar detalles de usuario pero cuando quiera usarlos, utilizará la API y eso podría romper algo más.

Cuestiones relacionadas