c# - Lock user if failed 5 attempts -


i can decrease attemptsleft in database set 5. attemptsleft decreased 1 if enter password wrongly correct username. can make user not log in system if user's status suspended.

problem:

i set when attemptsleft gets decreased 0, user's status become suspended. however, attemptsleft in database gets decreased , user's status not become suspended, gets suspended if enter username , password correctly, no matter how many attemptsleft lefts.

what wrong?

i think user.attempts retrieving database not working, , because user.attempts 0, attemptsleft in database gets decreased, because decreasing query.

here code using:

usermanager class:

public void getattempts(string username, string password)         {             logincontext context = new logincontext();              using (sqlconnection conn = new sqlconnection(connectionstring))             {                 string query = "select [username], [password], [attemptsleft] [information] [username] = @username , [password] = @password";                  conn.open();                  using (sqlcommand cmd = new sqlcommand(query, conn))                 {                     cmd.parameters.add("@username", sqldbtype.nvarchar);                     cmd.parameters["@username"].value = username;                      cmd.parameters.add("@password", sqldbtype.nvarchar);                     cmd.parameters["@password"].value = password;                      using (sqldatareader reader = cmd.executereader())                     {                         while (reader.read())                         {                             context.attempts = convert.toint32(reader["attemptsleft"]);                         }                     }                 }                  conn.close();             }         }  public bool checkuser(string username, string password)         {             using (sqlconnection conn = new sqlconnection(connectionstring))             {                 _query = "select [username], [password] [information] [username] = @username , [password] = @password";                  conn.open();                  using (sqlcommand cmd = new sqlcommand(_query, conn))                 {                     cmd.parameters.add("@username", sqldbtype.nvarchar);                     cmd.parameters["@username"].value = username;                      cmd.parameters.add("@password", sqldbtype.nvarchar);                     cmd.parameters["@password"].value = password;                      using (sqldatareader reader = cmd.executereader())                     {                         if (reader.hasrows)                         {                             return true;                         }                          else                         {                             return false;                         }                     }                 }             }         }   public bool checkstatus(string username, string password)         {             using (sqlconnection conn = new sqlconnection(connectionstring))             {                 _query = "select [username], [currentstatus] [information] [username] = @username , [currentstatus] = @currentstatus";                  conn.open();                  using (sqlcommand cmd = new sqlcommand(_query, conn))                 {                     cmd.parameters.add("@username", sqldbtype.nvarchar);                     cmd.parameters["@username"].value = username;                      cmd.parameters.add("@currentstatus", sqldbtype.nvarchar);                     cmd.parameters["@currentstatus"].value = "active";                      using (sqldatareader reader = cmd.executereader())                     {                         if (reader.hasrows)                         {                             return true;                         }                          else                         {                             return false;                         }                     }                 }             }         }  public bool suspenduser(string username)         {             bool flag = false;              using (sqlconnection conn = new sqlconnection(connectionstring))             {                 string query = "select [username], [currentstatus] [information] [username] = @username";                  string _query = "update [information] set [currentstatus] = @currentstatus [username] = @username";                  conn.open();                  using (sqlcommand cmd = new sqlcommand(query, conn))                 using (sqlcommand _cmd = new sqlcommand(_query, conn))                 {                     cmd.parameters.add("@username", sqldbtype.nvarchar);                     cmd.parameters["@username"].value = username;                      _cmd.parameters.add("@username", sqldbtype.nvarchar);                     _cmd.parameters["@username"].value = username;                      _cmd.parameters.add("@currentstatus", sqldbtype.nvarchar);                     _cmd.parameters["@currentstatus"].value = "suspended";                      flag = convert.toboolean(_cmd.executenonquery());                 }                  conn.close();             }              return flag;         }  public bool decreaseattempts(string username)         {             bool flag = false;              using (sqlconnection conn = new sqlconnection(connectionstring))             {                 string query = "select [username], [attemptsleft] [information] [username] = @username";                  string _query = "update [information] set [attemptsleft] = [attemptsleft] - 1 [username] = @username";                  conn.open();                  using (sqlcommand cmd = new sqlcommand(query, conn))                 using (sqlcommand _cmd = new sqlcommand(_query, conn))                 {                     cmd.parameters.add("@username", sqldbtype.nvarchar);                     cmd.parameters["@username"].value = username;                      _cmd.parameters.add("@username", sqldbtype.nvarchar);                     _cmd.parameters["@username"].value = username;                      flag = convert.toboolean(_cmd.executenonquery());                 }                  conn.close();             }              return flag;         } 

logincontext model:

public int attempts         {             get;             set;         } 

controller:

usermanager manager = new usermanager();  [httpget]         public actionresult login()         {             return view();         }  [httppost]         public actionresult login(logincontext user, string username, string password)         {             if (!request.isauthenticated)             {                 if (modelstate.isvalid)                 {                     // `if` statement below gets executed when enter password , username correctly.                     if (manager.checkuser(username, password))                     {                         // `if` statement below gets executed when user's status not `suspended`                         if (manager.checkstatus(username, password))                         {                             manager.getattempts(username, password);                              // `if` statement below not gets executed. `user.attempts` `0`.                             if (user.attempts > 0)                             {                                  formsauthentication.setauthcookie(user.username, false);                                   return redirecttoaction("list", "home");                             }                              //`else` statement below gets executed whenever enter username , password correctly.                             else                             {                                 modelstate.addmodelerror(string.empty, "the account: " + username + ", has been locked due many failed login attempts!");                                  manager.suspenduser(username);                             }                         }                          //`else` statement below gets executed when user's status `suspended`.                         else                         {                             modelstate.addmodelerror(string.empty, "your account has been locked due many failed login attempts!");                         }                     }                      // `else` statement below gets executed when enter password wrongly , username correctly or vice versa.                     else                     {                         modelstate.addmodelerror(string.empty, "username or password incorrect!");                          manager.decreaseattempts(username);                     }                 }                  return view(user);             }          } 

if follow scenario when user not valid decresases invalid attempts. doesnt suspend user unless enter login credentials correctly.

really sudo logic should go:

  1. validate credentials
    1. credentials valid
      1. check account status, suspended deny access
      2. reset attempts 5
      3. allow user application
    2. credentials invalid
      1. decrease attempts one
      2. set account suspended if required

alot of logic can bound 1 or 2 methods. in decreaseattempts() method have 2 sql commands sql command cmd never executed

here example of doing in 1 method returning enum of status. basic example requires 1 method execute full authorization methods. have commented teh code.

public partial class usermanager  {      const int maxattempts = 5;      public loginstatus validateuser(string username, string password)     {         if (string.isnullorwhitespace(username))             throw new argumentnullexception("username");          //set password empty if null         password = password ?? "";          //create connection         using (var connection = new sqlconnection(configuration.connectionstring))         {             //assign local variables             int attemptsleft = maxattempts;             string currentstatus = "active";             string userpassword = null;              //get information user, query username have data. match password later on             string query = "select top(1) [username], [password], [attemptsleft], [currentstatus] [information] username = @username";              using (var command = new sqlcommand(query, connection))             {                 command.parameters.addwithvalue("@username", username);                 command.commandtype = system.data.commandtype.text;                  connection.open();                  using (var reader = command.executereader())                 {                     //no rows.. invalid username                     if (!reader.hasrows)                     {                         connection.close();                         return loginstatus.invalidcredentials;                     }                      //read first row (hence break)                     while (reader.read())                     {                         attemptsleft = (int)reader["attemptsleft"];                         currentstatus = (string)reader["currentstatus"];                         userpassword = (string)reader["password"];                         break;                     }                     reader.close();                 }                 connection.close();             }              //if account suspended dont bother password checking             if (currentstatus.equals("suspended", stringcomparison.currentcultureignorecase))             {                 return loginstatus.suspended;             }              //invalid password lets handle invalid credentials logic             if (!password.equals(userpassword))             {                 attemptsleft -= 1;                  //decrease attempts, lets stop @ 0 dont need negative attempts                 if(attemptsleft >= 0)                 {                     query = "update [information] set [attemptsleft] = @attemptsleft username = @username";                     using (var command = new sqlcommand(query, connection))                     {                         command.parameters.addwithvalue("@username", username);                         command.parameters.addwithvalue("@attemptsleft", attemptsleft);                         connection.open();                         command.executenonquery();                         connection.close();                     }                 }                  //suspend account when attempts less or equal 0                 if (attemptsleft <= 0)                 {                     query = "update [information] set [currentstatus] = @currentstatus username = @username";                     using (var command = new sqlcommand(query, connection))                     {                         command.parameters.addwithvalue("@username", username);                         command.parameters.addwithvalue("@currentstatus", "suspended");                         connection.open();                         command.executenonquery();                         connection.close();                     }                     //exit method login account suspended                     return loginstatus.suspended;                 }                  //exit invalid login credentials                 return loginstatus.invalidcredentials;             }             //if here lets reset login attempts 5, , account status active valid login             query = "update [information] set [attemptsleft] = @attemptsleft, [currentstatus] = @currentstatus username = @username";             using (var command = new sqlcommand(query, connection))             {                 command.parameters.addwithvalue("@username", username);                 command.parameters.addwithvalue("@attemptsleft", maxattempts);                 command.parameters.addwithvalue("@currentstatus", "active");                 connection.open();                 command.executenonquery();                 connection.close();             }             //if got here every thing match             return loginstatus.authorized;         }     }  }  public enum loginstatus {     authorized,     invalidcredentials,     suspended } 

to use can simple below (note have change view redirections)

[httppost] public actionresult index(string username, string password) {     if(string.isnullorwhitespace(username))     {         this.modelstate.addmodelerror("", "invalid login credential. no username sent.");         return view();     }      var manager = new usermanager();      var result = manager.validateuser(username, password);      switch (result)     {         case loginstatus.authorized:             return redirecttoaction("about", "home");          case loginstatus.invalidcredentials:             this.modelstate.addmodelerror("", "invalid login credentials. username or password incorrect");             break;          case loginstatus.suspended:             this.modelstate.addmodelerror("", "account suspeneded");             break;     }      return view(); } 

just fun rewrote simple stored procedure.

create procedure validateuser     @username nvarchar(50),     @password nvarchar(50) begin      set nocount on;      declare @userpassword nvarchar(50) = null     declare @maxattempts int  = 5     declare @attemptsleft int = 5     declare @currentstatus nvarchar(50)      /*         return codes:         0 = authorized         1 = invalidcredentials         2 = suspended     */       select top(1) @userpassword = [username], @attemptsleft = [attemptsleft], @currentstatus = [currentstatus] [information] username = @username      if @userpassword null         begin             select 1 [result], @maxattempts [attemptsremaining]             return         end      --account suspended.. return suspended result     if @currentstatus = 'suspended'         begin             select 2 [result], 0 [attemptsremaining]             return         end      --passwords dont match (note case insensitive on default collation)     if @password null or @password <> @userpassword         begin             --decrease attempts             set @attemptsleft = @attemptsleft - 1              --if attempts left greater 0 set account active , decrease attempts remaining             if @attemptsleft > 0                 begin                     update [information] set [currentstatus] = 'active', attemptsleft = @attemptsleft username = @username                     select 1 [result], @attemptsleft [attemptsremaining]                     return                 end             --else attempts left less or equal 0 therefore should suspended , attempts left set 0 (dont want negative attempts)             else                 begin                     update [information] set [currentstatus] = 'suspended', attemptsleft = 0 username = @username                     select 2 [result], 0 [attemptsremaining]                     return                 end         end     --if here , can reset account status , max attempts next login attempt     update [information] set [currentstatus] = 'active', attemptsleft = @maxattempts username = @username     select 0 [result], @maxattempts [attemptsremaining]  end go 

then calling simple (note have changed return type call returns both status , attempts remaining.

method

public loginresult validateuserstoredprocedure(string username, string password) {     if (string.isnullorwhitespace(username))         throw new argumentnullexception("username");      //set password empty if null     password = password ?? "";      //create connection     using (var connection = new sqlconnection(configuration.connectionstring))     {         var result = new loginresult         {             attemptsremaining = 5,             status = loginstatus.invalidcredentials         };         try         {             using (var command = new sqlcommand("exec validateuser @username, @password", connection))             {                 command.parameters.addwithvalue("@username", username);                 command.parameters.addwithvalue("@password", password);                 command.commandtype = system.data.commandtype.text;                 connection.open();                 using (var reader = command.executereader())                 {                     while (reader.read())                     {                         result.status = ((loginstatus)(int)reader["result"]);                         result.attemptsremaining = (int)reader["attemptsremaining"];                         break;                     }                     reader.close();                 }                 connection.close();             }             return result;         }         catch (exception ex)         {             if (connection.state != system.data.connectionstate.closed)                 connection.close();              debug.writeline("error on sql query:" + ex.message);             return result;         }     } } 

result class

public class loginresult {     public loginstatus status { get; set; }      public int attemptsremaining { get; set; } }  public enum loginstatus : int {     authorized = 0,     invalidcredentials = 1,     suspended = 2 } 

controller

[httppost] public actionresult index(string username, string password) {     if (string.isnullorwhitespace(username))     {         this.modelstate.addmodelerror("", "invalid login credential. no username sent.");         return view();     }     var manager = new usermanager();     var result = manager.validateuserstoredprocedure(username, password);     switch (result.status)     {         case loginstatus.authorized:             return redirecttoaction("about", "home");          case loginstatus.invalidcredentials:             if (result.attemptsremaining < 5)                 this.modelstate.addmodelerror("", "invalid login credentials. username or password incorrect. attempts remaining:" + result.attemptsremaining);             else                 this.modelstate.addmodelerror("", "invalid login credentials. username or password incorrect.");             break;          case loginstatus.suspended:             this.modelstate.addmodelerror("", "account suspeneded");             break;     }     return view(); } 

how optimize level of authorization rather weak. shows storing passwords plain text. topic together.


Comments

Popular posts from this blog

PHP DOM loadHTML() method unusual warning -

python - How to create jsonb index using GIN on SQLAlchemy? -

c# - TransactionScope not rolling back although no complete() is called -