Home > Software design >  Not able to create user and update user in Database from web service
Not able to create user and update user in Database from web service

Time:10-28

This might be repeated question, but I am not able to find the solution for it. I have a web service coded in C# and .net core through which I am trying to create a user in the database (SQL Server Management Studio). The query works fine when I try to create the user through SSMS, but it does not work through the function. Below is the function:

     public async Task CreateUserNameQuery(string username, string password)
        { 

object[] sqlParams = {new SqlParameter("@username", username),  new SqlParameter("@password", password)};
           
            
            string query3 = "IF USER_ID ('{@username}') IS NULL "   "\n"  
                            "CREATE USER {@username} WITH PASSWORD=N'{@password}', DEFAULT_SCHEMA=[dbo] "   "\n"  
                            "ELSE "   "\n"  
                            "ALTER USER {{@username}} WITH PASSWORD=N'{{@password}}', DEFAULT_SCHEMA=[dbo] "   "\n"  
                            "GO "   "\n"  
                            "sys.sp_addrolemember @rolename = N'db_datareader', @membername = N'{{@username}}' "   "\n"  
                            "GO ";

           var result = await Database.ExecuteSqlRawAsync(query3, sqlParams);
            
          
            Database.SetCommandTimeout(600);
        }

Below is the exception I get:

Input string was not in a correct format.


    at System.Text.StringBuilder.FormatError()
   at System.Text.StringBuilder.AppendFormatHelper(IFormatProvider provider, String format, ParamsArray args)
   at System.String.FormatHelper(IFormatProvider provider, String format, ParamsArray args)
   at System.String.Format(String format, Object[] args)
   at Microsoft.EntityFrameworkCore.Storage.Internal.RawSqlCommandBuilder.Build(String sql, IEnumerable`1 parameters)
   at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.ExecuteSqlRawAsync(DatabaseFacade databaseFacade, String sql, IEnumerable`1 parameters, CancellationToken cancellationToken)
  

CodePudding user response:

How about we strip out anything non a-z in a username; it'll be pretty hard to inject anything as a result. This does introduce a rule that usernames must be ascii a-z, but does anyone really need a username of 'DROP TABLE Students;-- ? (If they really do, see bottom)

        public async Task CreateUserNameQuery(string username, string password)
        { 
            username = Regex.Replace(username, "[^a-z]", "");
           
            string query3 = $@"
IF DATABASE_PRINCIPAL_ID('{username}') IS NULL
    CREATE USER {username} WITH PASSWORD={{0}}, DEFAULT_SCHEMA=[dbo] 
ELSE
    ALTER USER {username} WITH PASSWORD={{0}}, DEFAULT_SCHEMA=[dbo]";

            await Database.ExecuteSqlRawAsync(query3, username, password);

            await Database.ExecuteSqlInterpolatedAsync("EXECUTE sys.sp_addrolemember @rolename = N'db_datareader', @membername = {username}");
        }

I'm fairly sure you can parameterize the password, as it's presented as a string constant normally - it's just the username that's presented as an identifier - but I'm not in a position to test it. If it doesn't work out let me know

Final note; you can't send GO to SQLS server; SSMS breaks scripts up using GO as a delimiter and you should do this too (here I make two queries to mimic either side of the GO)


If you really need your username to contain all sorts of wacky stuff, perhaps it would be simplest to ask the db to quote it for you, and then use the quoted value in a string. Pick on any suitable object in your domain model that has a string property, such as Order and execute a raw query that quotes the username into the string property (let's imagine orderreference)

var x = (await context.Order.AsNoTracking().FromSqlInterpolated($"SELECT -1 as OrderId, QUOTENAME({username}) as OrderReference").FirstAsync()).OrderReference;

x would now contain, for an input of abc[]def, [abc[]]def] which can be safely concatenated into an sql in a position that cannot be parameterized

  • Related