Authorization on executing query on Progress OpenEdge with C# - c#

I have performed all the processes for installing and configuring the Progress OpenEdge version 11.7 database. I configured the DSN with username and password and to access the database I created and everything connected correctly.
After performing the connection to the database, I get the following error message when executing a query to get data:
Error:
ERROR [HY000] [DataDirect][ODBC Progress OpenEdge Wire Protocol driver][OPENEDGE]Access denied (Authorization failed) (7512)
I have accessed OpenEdge Management to guarantee all permissions for my user as shown below, but I still get this error message.
Code:
public static bool InsertItem(string itCodigo, string descItem, string um)
{
bool ret = false;
string connectString = "DSN=DSN-Name;uid=renan;pwd=*****;host=localhost;port=XXXX;db=DatabaseName;";
using (OdbcConnection connection = new OdbcConnection(connectString))
{
try
{
connection.Open();
IDbCommand dbcmd = connection.CreateCommand();
string sqlstr = "select * from Hipolabor.pub.Item";
dbcmd.CommandText = sqlstr;
using (IDataReader rdr = dbcmd.ExecuteReader())
{
var b = rdr.Read();
}
}
catch (Exception e)
{
return false;
}
finally
{
connection.Close();
}
}
return ret;
}
What could be wrong?

The permissions that you are showing from "data administration" are 4gl permissions. The 4gl and SQL-92 engines do not share permissions.
If nothing else has been done the initial SQL dba is the user who created the db. Depending on what version of Progress this is and how this database was setup and created you might also have a "sysprogress" user defined who might be the system DBA user.
The "renan" user id may not be a SQL user -- that also depends on the Progress version how this db has been setup.

Related

After querying an SQL database, and finding invalid login details, how can I display an error message in the HTML Page?

I am developing a login system using ASP.NET 7.0. I have created the login and signup system, by connecting to an SQL database and inserting or querying it for information. Currently, the backend code is able to create accounts, and check to make sure that while making an account, that their is no user with matching email or username. I would like to be able to display some sort of message saying "An account with those details has already been created, Login?". How would I go about this?
Here is my current code:
public void OnPostSignup()
{
System.Diagnostics.Debug.WriteLine("Post Request Received");
// Creating Credentials //
string InputUser = Request.Form["signup-user"];
string InputPassword = Request.Form["signup-pwd"];
string InputEmail = Request.Form["signup-email"];
// Creates a new SQL Connection using the connection string provided - Then runs an SQL Command: NOTHING HAS BEEN RUN YET, ONLY INSTANCIATED //
using (SqlConnection conn = new SqlConnection("Valid Server String Here"))
using (SqlCommand cmd = new SqlCommand("INSERT INTO AccountData ([User], [Password], [Email]) VALUES (#1, #2, #3);", conn))
{
// The Placeholder Values are replaced with the string variables created above containing our account registration data //
cmd.Parameters.AddWithValue("#1", InputUser);
cmd.Parameters.AddWithValue("#2", InputPassword);
cmd.Parameters.AddWithValue("#3", InputEmail);
// Instanciates a new SQL Command that will cehck the database to ensure an account with that infomation hasnt been created already //
using (SqlCommand UserCheck = new SqlCommand("SELECT * FROM AccountData WHERE [User] = #1 AND [Email] = #2", conn))
{
// Adds the inputted data into the UserCheck SQL Command //
UserCheck.Parameters.AddWithValue("#1", InputUser);
UserCheck.Parameters.AddWithValue("#2", InputEmail);
// A connection to our SQL Databasse is opened //
conn.Open();
// Executes a data reader on our SQL Server
SqlDataReader reader= UserCheck.ExecuteReader();
// This logic gate checks if the reader returns any rows with the given infomation - if yes, no account is created, and the connection is closed - if no, the account creation is started //
if(reader.HasRows)
{
// We already have an account with the same email or username //
reader.Close();
conn.Close();
// Display some sort of message to the user saying that their email or username is already in use. //
}
else
{
// We do not have an account with that information - An account can now be created //
// Closes the reader, because we cannot query our SQL databse twice at the same time //
reader.Close();
// Executes the 'cmd' SQL command against our SQL Databse //
cmd.ExecuteNonQuery();
// Closes the connection to our SQL Databse for security - and cost //
conn.Close();
}
}
}
}
// This will run when the user clicks the "Login button, after filling out all the required fourm felids //
public void OnPostLogin()
{
// Takes the data inputted by the user, and stores them as variables to be ran against the SQL Database //
string LoginUser = Request.Form["login-user"];
string LoginPass = Request.Form["login-passwrd"];
// Defines an SQL Connection with our SQL Connection String //
using (SqlConnection conn = new SqlConnection("Valid Connection String Here"))
// Creates a new SQL command that checks the database for a account; notice that '#1' amd '#2' are placeholders //
using (SqlCommand cmd = new SqlCommand("SELECT * FROM AccountData WHERE [User] = #1 AND [Password] = #2", conn))
{
// Replaces the placeholder values in the SQL command with our varaibles that were created from the users input
cmd.Parameters.AddWithValue("#1", LoginUser);
cmd.Parameters.AddWithValue("#2", LoginPass);
// A connection is opened to our SQL Database //
conn.Open();
// Executes the SQL Database reader with the paramaters defined in our SQL Command 'cmd' //
SqlDataReader reader = cmd.ExecuteReader();
// Checks if the SQL reader returned any rows //
if (reader.HasRows)
{
// User Exists //
reader.Close();
System.Diagnostics.Debug.WriteLine("We have found an account");
// Log in the user //
}
else
{
// User Doesnt Exist //
reader.Close();
System.Diagnostics.Debug.WriteLine("No Account Found");
}
// Closes the connection to our SQL Database //
conn.Close();
}
}
I am aware that the code may be vunrable to SQL injection attacks! the website has not been published yet, and security will be added before launch.
I appreciate any help that I receive, if there is anything that doesn't make sense, please let me know!
Thanks for the help everybody! However, i have found a solution to the problem. Inside of the if statement where login details are verified, i added this onto the 'invalid login' return.
ModelState.AddModelError("InvalidLogin", "Invalid login details");
And then, directly below my login form i added the following code
#if (Model.ModelState.ContainsKey("InvalidLogin"))
{
<div class="alert alert-danger">#Model.ModelState["InvalidLogin"].Errors[0].ErrorMessage</div>
System.Diagnostics.Debug.WriteLine("Error message displayed in view");
}
else
{
System.Diagnostics.Debug.WriteLine("No error message to display in view");
}
If you are viewing this post late, looking for an answer, this worked well for me. If you would like help setting this up for your code feel free to # me

Microsoft.Data.SqlClient.SqlException (0x80131904): Login failed for user '<token-identified principal>'. Token is expired

I am using Entity Framework to connect to an Azure SQL database and I'm connecting using an access token (obtained via the Managed Identities).
I am not using user name and password in the SQL connection string and using managed identity and keeping SQL connection string in Azure keyvault.
I'm connecting to the database with a token like shown below, but after an hour it expires, so I'm getting "SQL login failed - " errors.
I have a long running process once connected the the database, and it collects some config data from some tables, and after more than 45 minutes, I need to update data in the database. When trying to save changes using dbcontext, the code is throwing this timeout issue.
How to get a new refreshed token and set to connection?
public SqlConnection GetDBConnection()
{
SqlConnection conn = new SqlConnection();
conn.ConnectionString = Environment.GetEnvironmentVariable("SqlConnectionString");
var credential = new DefaultAzureCredential();
var accessToken = credential.GetToken(new TokenRequestContext(new[] { "https://database.windows.net/.default" }));
conn.AccessToken = accessToken.Token;
return conn;
}
We need to make sure that the connection is not closed until the job is done, and coming to the token part it might expire when we have any connection issue when we run long processes.
So as we got some insights in the comments section to use “USING”. This can be done.
Below is how we use it for connections, mostly for SQL:
using (SqlConnection conn = new SqlConnection(...))
{
using(SqlCommand cmd = new SqlCommand(..., conn))
{
conn.Open();
using(DataReader dr = cmd.ExecuteReader()) // or load a DataTable, ExecuteScalar, etc.
{
...
{
}
}
Also check for AAD Authentication with Azure SQL Database as we have seen token-identified-principal.

How to fix “Invalid operation on a closed object” exception when trying to Read an OracleDataReader

I'm creating a web API using .Net Core and the Oracle.ManagedDataAccess.Core plugin that accesses an Oracle database to retrieve a Blob field and return it as a byte array. I created a function (getBlobfromDB) that gets the Oracle connection string from an encrypted field on a SQL database, connects and uses an OraleDataReader to retrieve and return the Blob field. But when the OraleDataReader tries to Read the record, I'm getting this exception: "Invalid operation on a closed object".
When you search for this issue, the most relevant answer is this post
However, I'm 100% percent sure that user on the conn string has access since that is the schema owner, and I also tried adding the schema owner to the Select query (SELECT FIELD FROM SCHEMA_OWNER.TABLE WHERE ID = "") getting the same error
So I tried two other things, getting a different VARCHAR field from another table on the same database, still getting the same error; and trying on a different Oracle database and I was able to successfully retrieve the data. I noticed that the Oracle versions on the servers are different, 12.2 for the working one and 11.2 for the non-working, this may be the reason? I don't know what else I can do or try, I'll appreciate any help/advice that you can give me
This is the simplified function
private OracleBlob getBlobfromDB(string sSystem, string sID)
{
string sSQL = String.Empty;
string connString = String.Empty;
OracleConnection oConn = new OracleConnection();
if (string.IsNullOrWhiteSpace(sID) || string.IsNullOrWhiteSpace(sSystem) )
{
return null;
}
sSQL = "SELECT BLOB_FIELD FROM TABLE WHERE ID = " + sID;
connString = getConnectionString(sSystem);
try
{
using (oConn = new OracleConnection(connString))
{
oConn.Open();
OracleCommand oCom = new OracleCommand(sSQL, oConn);
OracleDataReader oDr = oCom.ExecuteReader();
if (oDr.HasRows)
{
//I'm able to reach to this point before getting the exception
oDr.Read();
OracleBlob blob = oDr.GetOracleBlob(0);
// Clean up
oDr.Close();
oDr.Dispose();
oCom.Dispose();
return blob;
}
else
{
// Clean up
oDr.Close();
oDr.Dispose();
oCom.Dispose();
return null;
}
}
}
catch (Exception x)
{
return null;
}
finally
{
oConn.Close();
}
}
With the Oracle.ManagedDataAccess dependency you should not Close() the connection and do not use the using clause. It seems that the dependency itself closes the connection at will.
Remove: using(){} keyword and oConn.Close() from your code.

C# - New Values not reflecting on Access Database using UPDATE SQL cmd

I'm having problems with updating a row in the Users table of my Access DB. Here is the code below:
private void SaveProfileInfo()
{
try
{
ChangeForeColorOfStatusMsg(Color.Black);
ChangeTextOfStatusMsg("Saving new profile information...");
const string cmd = #"UPDATE Users SET LastName=#LastName,FirstName=#FirstName,MiddleName=#MiddleName,Add_Num=#Add_Num,Add_Street=#Add_Street,Add_Brgy=#Add_Brgy,Add_City=#Add_City,MobileNumber=#MobileNumber,Gender=#Gender WHERE ID=#ID;";
var dbConn = new OleDbConnection(cs);
var dbCmd = new OleDbCommand(cmd, dbConn);
dbCmd.Parameters.AddWithValue("#ID", UserLoggedIn.ID);
dbCmd.Parameters.AddWithValue("#LastName", txtLastName.Text);
dbCmd.Parameters.AddWithValue("#FirstName", txtFirstName.Text);
dbCmd.Parameters.AddWithValue("#MiddleName", txtMiddleName.Text);
dbCmd.Parameters.AddWithValue("#Add_Num", txtUnitNum.Text);
dbCmd.Parameters.AddWithValue("#Add_Street", txtStreet.Text);
dbCmd.Parameters.AddWithValue("#Add_Brgy", GetBrgySelectedItem());
dbCmd.Parameters.AddWithValue("#Add_City", GetCitySelectedItem());
dbCmd.Parameters.AddWithValue("#MobileNumber", txtMobileNumber.Text);
dbCmd.Parameters.AddWithValue("#Gender", GetGenderSelectedItem());
dbConn.Open();
dbCmd.ExecuteNonQuery();
dbConn.Close();
ChangeForeColorOfStatusMsg(Color.MediumSeaGreen);
ChangeTextOfStatusMsg("All changes have been saved! This window will close itself after two seconds.");
Thread.Sleep(2000);
CloseForm();
}
catch (Exception)
{
ChangeForeColorOfStatusMsg(Color.Crimson);
ChangeTextOfStatusMsg("Something went wrong while we were connecting to our database. Please try again later.");
hasFinishedEditting = false;
}
}
This method will be done on a separate thread, when the user updates his profile information.
UserLoggedIn is actually a field of a User class (a class that defines a row in my table), which stores all the info of the user who's currently logged in.
When I run this, it does not produce any exceptions or errors. But when I check my table, the values are not updated.
I copy-pasted these codes from the registration form (which works) that I made with this system, and modified it into an UPDATE cmd than an INSERT cmd.
I also made Change Username and Password Forms that use the same cmd as shown below:
public void ChangePass()
{
try
{
ChangeForeColorOfMsg(Color.Silver);
ChangeTextOfMsg("Changing password...");
const string cmd = "update Users set Pass=#Pass where ID=#ID";
var dbConn = new OleDbConnection(cs);
var dbCmd = new OleDbCommand(cmd, dbConn);
dbCmd.Parameters.AddWithValue("#Pass", txtNewPass.Text);
dbCmd.Parameters.AddWithValue("#ID", UserLoggedIn.ID);
dbConn.Open();
dbCmd.ExecuteNonQuery();
dbConn.Close();
ChangeTextOfMsg("Password successfully changed!");
}
catch (Exception)
{
ChangeForeColorOfMsg(Color.Silver);
ChangeTextOfMsg("A problem occurred. Please try again later.");
}
}
And these codes work for me. So I'm really confused right now as to why this update cmd for the profile information isn't working... Is there something I'm not seeing here?
OleDb cannot recognize parameters by their name. It follows a strictly positional order when sending them to your database for updates. In your code above the first parameter is the #ID but this parameter is used last in your query. Thus everything is messed up.
You just need to move the add of the #ID parameter as last in the collection
As a side note, you should be very careful with AddWithValue. It is an handy shortcut, but it has a dark side that could result in wrong queries.
Take a look at
Can we stop using AddWithValue already?

How I can Select a Table from a SQL Server Database correctly?

I want to built a connection to a SQL Server database with a SELECT command.
The connection is ok but I get a error if I make a error. I want to get the Select values to a DataTable.
This I get if I try this:
The SELECT-Perssision was denied for UserApplicationRequests-Objekt, DB_CM0-Datenbank, dbo-Schema.
I use a Login Dialog in my application for building the connection string. In this form:
user id=[username];password=[password];server=[servername];Trusted_Connection=yes;database=DB_CM0
And here is my code for the SELECT command.
public DataTable GetDataTable(string sql)
{
using (con = new SqlConnection(connectionstring))
{
try
{
SqlCommand command = new SqlCommand(sql, con);
SqlDataAdapter adapter = new SqlDataAdapter(command);
DataTable tb = new DataTable();
adapter.Fill(tb);
con.Open();
command.ExecuteReader();
return tb;
}
catch (Exception)
{
return null;
}
}
}
My SQL command:
string sql = "SELECT * FROM [DB_CM0].[dbo].[UserApplicationRequests]";
its happening because of security issue..below steps might help you
Open SQL Server Management studio
Navigate to the database 'CNET_85731' >> Security >> Users
Right click on the one which you are using in your code
And finally, just uncheck 'db_denydatareader' inside "Database Role
membership" section.
Your connection string uses the sql authentication login method and integrated security login method simultaneously... Windows integrated security will have the priority in this case and attempt to use your windows user permissions to interact with the database... maybe this is not the behaviour you intended.

Categories