Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to enable SQL Application Role via Entity Framework

I'm now developing big government application with entity framework. at first i have one problem about enable SQL application role. with ado.net I'm using below code:

SqlCommand cmd = new SqlCommand("sys.sp_setapprole");
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Connection = _sqlConn;
            SqlParameter paramAppRoleName = new SqlParameter();
            paramAppRoleName.Direction = ParameterDirection.Input;
            paramAppRoleName.ParameterName = "@rolename";
            paramAppRoleName.Value = "AppRole";
            cmd.Parameters.Add(paramAppRoleName);

            SqlParameter paramAppRolePwd = new SqlParameter();
            paramAppRolePwd.Direction = ParameterDirection.Input;
            paramAppRolePwd.ParameterName = "@password";
            paramAppRolePwd.Value = "123456";
            cmd.Parameters.Add(paramAppRolePwd);

            SqlParameter paramCreateCookie = new SqlParameter();
            paramCreateCookie.Direction = ParameterDirection.Input;
            paramCreateCookie.ParameterName = "@fCreateCookie";
            paramCreateCookie.DbType = DbType.Boolean;
            paramCreateCookie.Value = 1;
            cmd.Parameters.Add(paramCreateCookie);

            SqlParameter paramEncrypt = new SqlParameter();
            paramEncrypt.Direction = ParameterDirection.Input;
            paramEncrypt.ParameterName = "@encrypt";
            paramEncrypt.Value = "none";
            cmd.Parameters.Add(paramEncrypt);

            SqlParameter paramEnableCookie = new SqlParameter();
            paramEnableCookie.ParameterName = "@cookie";
            paramEnableCookie.DbType = DbType.Binary;
            paramEnableCookie.Direction = ParameterDirection.Output;
            paramEnableCookie.Size = 1000;
            cmd.Parameters.Add(paramEnableCookie);

            try
            {
                cmd.ExecuteNonQuery();
                SqlParameter outVal = cmd.Parameters["@cookie"];
                // Store the enabled cookie so that approle  can be disabled with the cookie.
                _appRoleEnableCookie = (byte[]) outVal.Value;

            }
            catch (Exception ex)
            {
                result = false;
                msg = "Could not execute enable approle proc." + Environment.NewLine + ex.Message;
            }

But no matter how much I searched I could not find a way to implement on EF.

Another question is: how to Add Application Role to Entity data model designer?


I'm using the below code for execute parameter with EF:

AEntities ar = new AEntities();

            DbConnection con = ar.Connection;
            con.Open();
            msg = "";
            bool result = true;
            DbCommand cmd = con.CreateCommand();

            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Connection = con;
            var d = new DbParameter[]{
            new SqlParameter{ ParameterName="@r", Value ="AppRole",Direction =  ParameterDirection.Input}
          , new SqlParameter{ ParameterName="@p", Value ="123456",Direction =  ParameterDirection.Input}
           };
            string sql = "EXEC " + procName + " @rolename=@r,@password=@p";
            var s = ar.ExecuteStoreCommand(sql, d);

When run ExecuteStoreCommand this line return error:

Application roles can only be activated at the ad hoc level.

like image 373
Ehsan Farahani Avatar asked Jun 20 '26 15:06

Ehsan Farahani


1 Answers

I do it the following way (assuming Database First):

  1. I create the DbContext from the db and call it MyEntitiesBase
  2. I inherit from MyEntitiesBase to create MyEntities with the following code:

    public partial class MyEntities : MyEntitiesBase
    {
    
    private byte[] appRoleCookie;
    
    private void SetAppRole()
    {
        try
        {
            appRoleCookie = Database.SqlQuery<byte[]>(
                @"
                DECLARE @cookie VARBINARY(8000)
                DECLARE @r INT
                EXEC sp_setapprole 'user', 'pass', @fCreateCookie = true, @cookie = @cookie OUTPUT
                SELECT @cookie").First();
        }
        catch
        {
            throw new AuthenticationException();
        }
    }
    
    private void UnSetAppRole()
    {
        bool failed = Database.SqlQuery<bool>("DECLARE @result BIT; EXEC @result = sp_unsetapprole @cookie = " + appRoleCookie.ToHexadecimalString() + "; SELECT @result").First();
        if (failed)
            throw new SecurityException();
    }
    
    public MyEntities() : base()
    {
        Database.Connection.Open();
        SetAppRole();
    }
    
    private bool disposed = false;
    
    protected override void Dispose(bool disposing)
    {
        if (disposed)
            return;
        UnSetAppRole();
        Database.Connection.Close();
        disposed = true;
        base.Dispose(disposing);
    }
    }
    

Where ToHexadecimalString is an extension method for IEnumerable<byte>, as follows:

public static class BytesExtensions
{
    public static string ToHexadecimalString(this IEnumerable<byte> bytes)
    {
        return "0x" + string.Concat(bytes.Select(b => b.ToString("X2")));
    }
}

And that's it. Works with connection pooling on and everything. You just use this inherited version instead of the one generated by EF.

like image 196
Nahuel Prieto Avatar answered Jun 22 '26 09:06

Nahuel Prieto



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!