This question already has answers here:
Faster way to find out if a user exists on a system?
(4 answers)
Closed 4 years ago.
I am creating db users via a web application like so:
try
{
SetConnection(server);
string sql =
"USE [master]" +
" CREATE LOGIN" + " [TP1\\" + user + "] FROM WINDOWS WITH DEFAULT_DATABASE=[master], " +
"DEFAULT_LANGUAGE=[us_english] " +
"EXEC sys.sp_addsrvrolemember #loginame = N'TP1\\" + user + "', #rolename = N'sysadmin'";
_tableContext.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, sql);
}
catch (Exception e)
{
// log error
throw e;
}
and it works fine.
I was testing the application and typed in a name that does not exist in WINDOWS-NT and got the followiing error:
Windows NT user or group 'TP1\MyName' not found. Check the name
again.\r\n'TP1\MyName' is not a valid login or you do not have
permission.\r\nChanged database context to 'master
After some time researching I found that I can SELECT * FROM sysusers
BUT this only shows me if a user is already registered on that server.
I would like to know if there is a way for me to check if the username is a valid NT-user?
This question will be marked as a duplicate but for the purpose of being clear I just wanted to share my specific scenario:
I found the answer here thanks to #SteveDrake.
My implementation :
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain))
{
user = "MyName";
UserPrincipal up = UserPrincipal.FindByIdentity(
pc,
IdentityType.SamAccountName,
user);
bool UserExists = (up != null);
}
NOTE I changed the ContextType to Domain
Related
I keep getting this exception over and over. I've tried separating my query into two separate queries, that didn't work. I've checked to make sure the db connection is closed elsewhere before it's opened during this method, it's definitely closed before the function is called and opened before any queries.
Below iss the code for the function. I've set breakpoints and the query itself is fine. The code is the exact same that I used previously for updating a PIN function, with just the query string changed, so I don't know why it's causing issues:
Code:
public void transferMoney(string senderIban, decimal senderBalance, string receiverIban, decimal transferAmount,string messageOptional)
{
//myBankAccount.AccountPin = updatedPin;
DataTable dtUser = new DataTable();
sqlconnConnection.Open();
string strQuery2 = #"UPDATE Accounts SET Balance = Balance + " + Convert.ToDecimal(transferAmount) + " WHERE GUID = '" + receiverIban + "';"
+ "UPDATE Accounts SET Balance = Balance - " + Convert.ToDecimal(transferAmount) + " WHERE GUID = '" + senderIban + "';";
// example of a Paramaterised SQL statement.
SQLiteCommand sqlcomCommand2 = new SQLiteCommand(strQuery2, sqlconnConnection);
SQLiteDataAdapter sqldatadptAdapter = new SQLiteDataAdapter(sqlcomCommand2); // local SQL data Adaptor
try
{
// sqldatadptAdapter.Fill(dtUser);
sqlcomCommand2.ExecuteNonQuery();
}
catch (Exception ex)
{
// Exception will the "thrown" when there was a problem
throw new Exception($"UPDATE WAS unsuccessful:\n{ex.Message}");
}
finally
{
sqlconnConnection.Close();
}
Maybe you have a DB browser opened? Or you have accessed the DB some other way. This error only occurs when DB is modified or used elsewhere. If you can't find it, I'd suggest restarting PC just in case there something hidden :)
P.S. Posting this as answer as I cannot comment under the question for technical reasons :)
Just to clear the wind I am aware off that granting users sysadmin in T-SQL in not a good thing but per customer requirements it needs to be done.
I have this :
public void AddUserToServer(List<string> users, List<string> servers)
{
foreach (var server in servers)
{
setConnection(server);
foreach (var user in users)
{
string sql =
"USE [master]" +
" CREATE LOGIN" + " [TP1\\" + user + "] FROM WINDOWS WITH DEFAULT_DATABASE=[master], " +
"DEFAULT_LANGUAGE=[us_english] " +
"EXEC sys.sp_addsrvrolemember #loginame = N'TP1\\" + user + "', #rolename = N'sysadmin'";
_dbContext.Database.ExecuteSqlCommand(sql);
}
}
}
I got the above script by creating the user manually in ssms and then generated the script. However when running it I am getting this current error:
'The procedure 'sys.sp_addsrvrolemember' cannot be executed within a transaction.
So I changed it to :
string sql =
"USE [master]" +
" CREATE LOGIN" + " [TP1\\" + user + "] FROM WINDOWS WITH DEFAULT_DATABASE=[master], " +
"DEFAULT_LANGUAGE=[us_english] " +
"GRANT ADMINISTER BULK OPERATIONS TO[TP1\\" + user + "]";
This creates the user BUT I do not get the sysadmin role.
How do I solve this?
So typical that I spent some time on this and finally after positing I find the answer.
I believe that this is a question more people will ask so I can provide what I found:
string sql =
"USE [master]" +
" CREATE LOGIN" + " [TP1\\" + user + "] FROM WINDOWS WITH DEFAULT_DATABASE=[master], " +
"DEFAULT_LANGUAGE=[us_english] " +
"EXEC sys.sp_addsrvrolemember #loginame = N'TP1\\" + user + "', #rolename = N'sysadmin'";
_dbContext.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, sql);
NOTE:
TransactionalBehavior.DoNotEnsureTransaction
Starting with EF6 Database.ExecuteSqlCommand() by default will wrap
the command in a transaction if one was not already present. There are
overloads of this method that allow you to override this behavior if
you wish. Also in EF6 execution of stored procedures included in the
model through APIs such as ObjectContext.ExecuteFunction() does the
same (except that the default behavior cannot at the moment be
overridden).
Found the answer here
This question already has answers here:
ASP.NET Identity 2.0 check if current user is in role IsInRole
(4 answers)
Unable to configure AspNet.Identity using PostgreSQL
(2 answers)
Closed 4 years ago.
I have a little web application on asp.net MVC + PostgreSQL.
I have login page, where people enters their login/password. Right now I only have 1 user - admin. If login and pass are correct, I enter to mainForm.aspx page.
But I need to make a couple of users: user and director. When user logs in, he needs to be redirected to user.aspx page, when director logs in, he needs to be redirected to director.aspx page. All cases need to make login/pass check from PostgreSQL database.
How do I do that?
Here's my Login.aspx.cs code with only 1 user:
namespace User1.WebApp
{
public partial class Login : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
this.UnobtrusiveValidationMode = System.Web.UI.UnobtrusiveValidationMode.None;
}
protected void Button_Login_Click(object sender, EventArgs e)
{
var connString = "Host=localhost;Username=postgres;Password=123;Database=postgres";
using (var conn = new NpgsqlConnection(connString))
{
conn.Open();
string checkuser = "select count(*) from Login where name= '" + TextBoxUserName.Text + "' ";
NpgsqlCommand com = new NpgsqlCommand(checkuser, conn);
int temp = Convert.ToInt32(com.ExecuteScalar().ToString());
if (temp == 1)
{
string checkPasswordQuery = "select password from Login where name= '" + TextBoxUserName.Text + "'";
NpgsqlCommand passCom = new NpgsqlCommand(checkPasswordQuery, conn);
string password = passCom.ExecuteScalar().ToString().Replace(" ", "");
if (password == TextBoxPassword.Text)
{
Session["New"] = TextBoxUserName.Text;
Response.Redirect("MainForm.aspx");
}
else
{
Response.Write("Password is NOT correct !");
}
}
else
{
Response.Write("Username is NOT correct !");
}
}
}
}
}
You could do this just before
Response.Redirect("MainForm.aspx");
The way you can do it is to check the type of user and act accordingly.
Few comments regarding the current code:
Set the connection string in web.config and read it from there instead of having it hard coded in your code e.g. here.
The way you create your SQL statements makes your application vulnerable to SQL injection, one of the most common ways for someone to hack a site. Instead of doing this, prefer parameterized queries.
You make two round trips to the database, to check if the user exists and then to get her password. What about if you want to fetch one more information like the user type ? You would make one more round trip. You could eliminate all this to one round trip, provided that you can identify your users based on something unique like the username. Just fetch all the data for a specific username.
Let that someone can get access to the Login table of your database. How exposed are your application users ? 100%. All the passwords there are in clear text ! You should avoid this in any way. A naive solution is to hash the password and each time someone try to login to hash the password that the user provides and compare with the hash you have stored. A more professional approach of storing passwords is described at The right way to implement password hashing using PBKDF2 and C#. Look also for similar articles like the mentioned one. Security should be of paramount importance for your applications.
Are you able to store an extra field in the database to specify whether a login is Admin, User or Director?
You could use an Enum for this:
enum LoginRole
{
User = 0,
Director = 1,
Admin = 2
}
This Enum could be stored as an integer field in your Login table, called "role" or similar. You could then redirect to the appropriate page depending on this role.
I have updated your code with an example:
var connString = "Host=localhost;Username=postgres;Password=123;Database=postgres";
using (var conn = new NpgsqlConnection(connString))
{
conn.Open();
string checkuser = "select password, role from Login where name=#username";
using (var com = new NpgsqlCommand(checkuser, conn))
{
com.Parameters.AddWithValue("#username", TextBoxUserName.Text);
using (var reader = com.ExecuteReader())
{
if (reader.Read())
{
string password = reader["password"].ToString();
LoginRole role = (LoginRole)reader["role"];
if (password == TextBoxPassword.Text)
{
Session["New"] = TextBoxUserName.Text;
switch (role)
{
case LoginRole.User:
Response.Redirect("user.aspx");
break;
case LoginRole.Admin:
Response.Redirect("MainForm.aspx");
break;
case LoginRole.Director:
Response.Redirect("director.aspx");
break;
}
}
else
Response.Write("Password is NOT correct !");
}
else
Response.Write("Username is NOT correct !");
}
}
}
Please note, using parameters in your queries in this case would be preferred, as appending the string from the textbox straight into the SQL query is vulnerable to SQL injection.
You were also making two calls to the database per login - one to check the username and another to check the password. I have addressed this in my above sample to only make one call to the database.
So, for a few days i've been trying to do this, still, i've passed trough a few problems but im stuck on this one. looks like my connection to AD is working fine (after alot of digging and googling)
i have this.
I'm not a developer, still i have studied c# in school and i have some knowledge of it, still, i need to make this work in order to save time when it comes the time to create a new user.
private void btn_create_Click(object sender, EventArgs e)
{
bool valid = false;
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "PTLISDC04", "Users");
{
valid = ctx.ValidateCredentials("myadminaccount", "mypassword");
}
UserPrincipal usr = new UserPrincipal(ctx);
usr.UserPrincipalName = tb_user.Text.ToString() + "#kpmg.com";
usr.Name = tb_lname.Text.ToString() + ", " + lb_fname.Text.ToString() + " " + lbl_mname.Text.ToString();
usr.Description = tb_empid.Text.ToString();
usr.EmailAddress = tb_email.Text.ToString();
usr.DisplayName = tb_lname.Text.ToString() + ", " + lb_fname.Text.ToString() + " " + lbl_mname.Text.ToString();
usr.Save();
usr.Dispose();
ctx.Dispose();
MessageBox.Show("User Created!");
and when i press the "create user" button i get this:
An unhandled exception of type
'System.DirectoryServices.AccountManagement.PrincipalOperationException'
occurred in System.DirectoryServices.AccountManagement.dll
Additional information: An invalid dn syntax has been specified.
and it points to this line on code
usr.UserPrincipalName = tb_user.Text.ToString() + "#kpmg.com";
if i comment this line it goes to the next and so on
There is something terribly wrong below but i just cannot figure out what.
Although the website is created like a charm, the Application pool that should be associated with it, is not created at all.
public string Create(string sitename)
{
try
{
using (ServerManager serverMgr = new ServerManager())
{
string strhostname = sitename + "." + domain;
string bindinginfo = ":80:" + strhostname;
if (!IsWebsiteExists(serverMgr.Sites, strhostname))
{
Site mySite = serverMgr.Sites.Add(strhostname, "http", bindinginfo, "C:\\admin\\" + domain);
ApplicationPool newPool = serverMgr.ApplicationPools.Add(strhostname);
newPool.ManagedRuntimeVersion = "v4.0";
newPool.ManagedPipelineMode = ManagedPipelineMode.Integrated;
serverMgr.CommitChanges();
return "Website " + strhostname + " added sucessfully";
}
else
{
return "Name should be unique, " + strhostname + " already exists.";
}
}
}
catch (Exception ex)
{
return ex.Message;
}
}
What am i doing wrong here?
What's happening here is that when you create your site it automatically gets assigned to the DefaultAppPool.
What you need to do is replace your site's root Application (/) and point it at the application pool you just created.
The easiest way to do this is to first clear your new site's Application collection, then add a new root application that points to your application pool.
Taking your code snippet I changed it to the following:
Site mySite = serverMgr.Sites.Add(strhostname, "http", bindinginfo, "C:\\admin\\" + domain);
// Clear Applications collection
mySite.Applications.Clear();
ApplicationPool newPool = serverMgr.ApplicationPools.Add(strhostname);
newPool.ManagedRuntimeVersion = "v4.0";
newPool.ManagedPipelineMode = ManagedPipelineMode.Integrated;
// Create new root app and specify new application pool
Application app = mySite.Applications.Add("/", "C:\\admin\\" + domain);
app.ApplicationPoolName = strhostname;
serverMgr.CommitChanges();
I wouldnt expect the App Pool name to have punctuation in it. Adding the domain as part of the app pool name is a little unusual - perhaps thats the source. The basic method is discussed here, along with the appcmd syntax to make the same thing happen on the command line - try creating your app pool on the cmd line to see if your parameters are acceptable.
Create an application pool that uses .NET 4.0