0% found this document useful (0 votes)
2 views

Setting-up-with-Database

The document outlines the setup of a user authentication system using ASP.NET MVC, including a UserName model for validating usernames and passwords, a UsernameController for handling user input, and methods for saving and verifying credentials. It details the use of BCrypt.Net for secure password hashing and includes instructions for creating views for user input and success messages. Additionally, it describes the implementation of a login mechanism to retrieve stored data after submission.

Uploaded by

Rodmel Cabrera
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Setting-up-with-Database

The document outlines the setup of a user authentication system using ASP.NET MVC, including a UserName model for validating usernames and passwords, a UsernameController for handling user input, and methods for saving and verifying credentials. It details the use of BCrypt.Net for secure password hashing and includes instructions for creating views for user input and success messages. Additionally, it describes the implementation of a login mechanism to retrieve stored data after submission.

Uploaded by

Rodmel Cabrera
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 17

Setting up with Database

1. UserName Model

No changes from previous lesson.


using System.ComponentModel.DataAnnotations;

namespace lesson1.Models
{
public class UserName
{
[Required(ErrorMessage = "Username is required.")]
[RegularExpression(@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+=-])[a-zA-Z0-
9!@#$%^&*()_+=-]+$",
ErrorMessage = "Username must contain at least one lowercase letter, one uppercase
letter, one digit, and one special character (!@#$%^&*()_+=-).")]
[StringLength(20, MinimumLength = 8, ErrorMessage = "Username must be between 8
and 20 characters long.")]
public string username { get; set; }

[Required(ErrorMessage = "Password is required.")]


[RegularExpression(@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+=-])[a-zA-Z0-
9!@#$%^&*()_+=-]+$",
ErrorMessage = "Password must contain at least one lowercase letter, one uppercase
letter, one digit, and one special character (!@#$%^&*()_+=-).")]
[StringLength(20, MinimumLength = 8, ErrorMessage = "Password must be between 8
and 20 characters long.")]
public string password { get; set; }
}
}
2. Controller

using lesson1.Models;
using Microsoft.AspNetCore.Mvc;
using System.IO; // new
using System.Text; // new
using BCrypt.Net; // new

namespace lesson1.Controllers
{
public class UsernameController : Controller
{
// new
private readonly string filePath = @"C:\Users\THOR\Desktop\UD-
R\UserCredentials.txt";

public IActionResult Index()


{
// new
ViewBag.Usernames = System.IO.File.Exists(filePath) ?
System.IO.File.ReadAllText(filePath) : "No usernames saved yet.";
return View();
}

[HttpPost]
public ActionResult Index(UserName unamemodel)
{
if (ModelState.IsValid)
{
// Hash the password before saving
string hashedPassword =
BCrypt.Net.BCrypt.HashPassword(unamemodel.password);

// Save username and hashed password


string userData = $"{unamemodel.username} | {hashedPassword}\n";
System.IO.File.AppendAllText(filePath, userData, Encoding.UTF8);

// new
ViewBag.Message = $"Username '{unamemodel.username}' saved!";
}
// new
ViewBag.Usernames = System.IO.File.Exists(filePath) ?
System.IO.File.ReadAllText(filePath) : "No usernames saved yet.";
return View();
}
}
}
using directive in C#

using System.IO;

1. using – This is a directive in C# that tells the compiler to include a specific


namespace. It allows you to use classes, interfaces, and functions from that namespace
without having to fully qualify them.

What "Fully qualify” Means?

"Fully qualify" means writing the full path of a class, function, or interface, including its
namespace.

For example, without using System;, you would have to write:

System.Console.WriteLine("Hello, world!");

But if you add using System; at the top, you can simply write:

Console.WriteLine("Hello, world!");

2. System.IO – This is a namespace in C# that provides functionalities for working with


input and output (I/O) operations, such as reading and writing files, handling
directories, and working with streams.

using System.Text;

1. using – A directive that allows the inclusion of a namespace.

2. System.Text – A namespace in C# that contains classes related to text processing


and character encoding.

using BCrypt.Net;

What is BCrypt.Net?

• BCrypt.Net is a third-party cryptographic library that provides secure password


hashing.
• It implements the BCrypt algorithm, which is widely used for storing
passwords securely.
• It includes built-in salting and adaptive hashing to protect against brute-force
attacks.

private readonly string filePath = @"C:\Users\THOR\Desktop\UD-R\UserCredentials.txt";

1. private (Access Modifier)

• private means this variable can only be accessed within the same class.

• It cannot be accessed from other classes or outside the class it's declared in.
2. readonly (Modifier)

• readonly makes the variable immutable after initialization.

• You can assign a value inside the constructor, but you cannot modify it later.

• Used to ensure the variable remains constant after object creation.

3. string (Data Type)

• string is a data type in C# that stores text (sequence of characters).

• In this case, filePath stores a file path as a string.

4. filePath (Variable Name)

• filePath is the name of the variable.

• It follows camelCase naming convention, which is commonly used in C# for


variables.

5. = @"C:\Users\THOR\Desktop\UD-R\UserCredentials.txt"; (Assignment & String


Literal)
• The = operator assigns a value to the variable.

• @ (Verbatim String Literal) is used to treat backslashes (\) as normal


characters, avoiding the need for double backslashes (\\).

Summary
private Accessible only within the class.
readonly Cannot be modified after initialization.
string Stores a text value.
filePath Variable name storing the path to a file.
= ... Assigns the file path value.
@ Verbatim string to prevent escape sequence issues in the file path.

public IActionResult Index()


{

ViewBag.Usernames = System.IO.File.Exists(filePath) ? System.IO.File.ReadAllText(filePath) : "No


usernames saved yet.";

return View();
}

1. ViewBag.Usernames =

• ViewBag: A dynamic object in ASP.NET MVC used to pass data from the
controller to the view.

• Usernames: A property being dynamically created under ViewBag. It will store


the usernames retrieved from the file (or a default message).

• =: Assignment operator, assigning a value to ViewBag.Usernames.


2. System.IO.File.Exists(filePath)

• System.IO: A namespace that provides file and directory handling functionalities.

• File.Exists(filePath):

o Checks if the file exists at the specified location (filePath).


o Returns true if the file exists, false otherwise.

3. ? : (Ternary Operator)

This is a ternary conditional operator, which works like an if-else statement:

4. System.IO.File.ReadAllText(filePath)

• Reads the entire contents of the file located at filePath and returns it as a string.

• If the file contains multiple usernames, they will be retrieved as a single string.

5. "No usernames saved yet."

• If the file does not exist, this default string is assigned to ViewBag.Usernames.

[HttpPost]
public ActionResult Index(UserName unamemodel)
{
if (ModelState.IsValid)
{
// Hash the password before saving
string hashedPassword = BCrypt.Net.BCrypt.HashPassword(unamemodel.password);

// Save username and hashed password


string userData = $"{unamemodel.username} | {hashedPassword}\n";
System.IO.File.AppendAllText(filePath, userData, Encoding.UTF8);

ViewBag.Message = $"Username '{unamemodel.username}' saved!";


}

ViewBag.Usernames = System.IO.File.Exists(filePath) ?
System.IO.File.ReadAllText(filePath) : "No usernames saved yet.";
return View();
}
}

string hashedPassword = BCrypt.Net.BCrypt.HashPassword(unamemodel.password);

1. string hashedPassword =

• string: This specifies that hashedPassword is a string data type.

• hashedPassword: A variable that will store the hashed version of the user's
password.

• =: Assignment operator, which assigns the hashed password to the variable.


2. BCrypt.Net.BCrypt.HashPassword(unamemodel.password)

This part is responsible for hashing the password. Let’s break it down:

🔹 BCrypt.Net.BCrypt

• BCrypt is a password-hashing algorithm that is designed to be slow and


resistant to brute-force attacks.

• BCrypt.Net: The namespace that contains the BCrypt class.


• BCrypt.HashPassword(...): A method that hashes a given password.

🔹 unamemodel.password

• unamemodel: This is an instance of the UserName model.

• password: A property of unamemodel, containing the user's plain-text password.

• This value is passed as an argument to HashPassword() for hashing.

Why Hash Passwords?

1. Security – If someone steals the database, they can't see plain-text


passwords.

2. One-Way Encryption – The hashed password cannot be reversed to get


the original password.

3. Brute-Force Protection – BCrypt is slow, making brute-force attacks


impractical.

string userData = $"{unamemodel.username} | {hashedPassword}\n";

1. string userData =

• string: Declares a variable of type string, which stores text.

• userData: The name of the variable that will hold the formatted string.

• =: Assignment operator, which assigns the formatted string to userData.

2. $"{unamemodel.username} | {hashedPassword}\n"

This is a string interpolation feature in C# ($"..."), which allows us to embed variables


inside a string.

🔹 $"..." (String Interpolation)

• The $ before the string enables interpolation, meaning variables can be


inserted directly inside {} braces.

• This is an alternative to concatenation (+) or string.Format().

🔹 {unamemodel.username}

• unamemodel: An instance of the UserName model.

• username: A property of unamemodel that holds the user's entered username.


• The value inside {} will be replaced with the actual username.
🔹"|"

• A separator (pipe symbol |) is used between the username and the hashed
password.

• This helps keep the stored data readable and structured.

🔹 {hashedPassword}

• Inserts the value of hashedPassword (the securely hashed password) into the
string.

🔹 \n (Newline Character)

• \n adds a new line, meaning each stored username-password pair will be written
on a separate line in the text file.

System.IO.File.AppendAllText(filePath, userData, Encoding.UTF8);

1. System.IO.File

• System.IO: A namespace in C# that provides file-handling functionalities.

• File: A class in System.IO that contains static methods for working with files,
such as reading, writing, and appending text.

2. AppendAllText(filePath, userData, Encoding.UTF8)

• AppendAllText(...): A method of the File class that appends text to an existing


file. If the file does not exist, it creates a new one.
• Parameters:

1. filePath: The path to the file where the data will be written.

2. userData: The text content that will be appended to the file.

3. Encoding.UTF8: Specifies that the file should be written using UTF-8


encoding, which supports a wide range of characters (including special
characters and symbols).
2. Index

@model lesson1.Models.UserName

<!DOCTYPE html>
<html>
<body>
<h2>Enter Credentials</h2>

@using (Html.BeginForm(FormMethod.Post))
{
<div class="mb-3">
@Html.LabelFor(model => model.username, "Username:", new { @class =
"form-label" })
@Html.TextBoxFor(model => model.username, new { @class = "form-control",
placeholder = "Enter your username" })
@Html.ValidationMessageFor(model => model.username, "", new { @class =
"text-danger" })
</div>

<div class="mb-3">
@Html.LabelFor(model => model.password, "Password:", new { @class =
"form-label" })
@Html.PasswordFor(model => model.password, new { @class = "form-
control", placeholder = "Enter your password" })
@Html.ValidationMessageFor(model => model.password, "", new { @class =
"text-danger" })
</div>

<button type="submit" class="btn btn-primary">Submit</button>


}

@if (ViewBag.Message != null)


{
<div class="mt-3 alert alert-success">
<p>@ViewBag.Message</p>
</div>
}

@* NEW *@
<h3>Saved Usernames and Hashed Passwords:</h3>
<pre>@ViewBag.Usernames</pre>

</body>
</html>

Add below

<h3>Saved Usernames and Hashed Passwords:</h3>


<pre>@ViewBag.Usernames</pre>
Redirect to Another Page After Submission

Modify the Controller (UsernameController.cs)

Change the return View(); statement after successful submission to


RedirectToAction("Success").
[HttpPost]
public ActionResult Index(UserName unamemodel)
{
if (ModelState.IsValid)
{

string hashedPassword = BCrypt.Net.BCrypt.HashPassword(unamemodel.password);

string userData = $"{unamemodel.username} | {hashedPassword}\n";

System.IO.File.AppendAllText(filePath, userData, Encoding.UTF8);

// new
return RedirectToAction("Success");
}

ViewBag.Usernames = System.IO.File.Exists(filePath) ? System.IO.File.ReadAllText(filePath) : "No


usernames saved yet.";

// new
return View(unamemodel);
}

// new
public ActionResult Success()
{
return View();
}
}
}

Create a New View for Success Page (Success.cshtml)

This is the page users will see after submission.

Create Success.cshtml inside Views/Username/

<!DOCTYPE html>
<html>
<body>
<h2>Form Submitted Successfully!</h2>
<p>Your credentials have been saved.</p>

<a href="@Url.Action("Index", "Username")" class="btn btn-primary">Go Back</a>


</body>
</html>
Goal
• A submission page where the user enters their credentials.
• A retrieval page after submission, where the user enters their username and
password to check if they exist.
• A login page that confirms if the credentials are correct.

Changes Made:
• After submitting, the user is redirected to a login page where they enter their
credentials to retrieve stored data.
• If login credentials match the stored username and password, redirect to a
success page.

• Used BCrypt.Verify to check if the entered password matches the stored hashed
password.

1. Updated Code UsernameController.cs


using lesson1.Models;
using Microsoft.AspNetCore.Mvc;
using System.IO;
using System.Text;
using BCrypt.Net;

namespace lesson1.Controllers
{
public class UsernameController : Controller
{

private readonly string filePath = @"C:\Users\THOR\Desktop\UD-


R\UserCredentials.txt";

public IActionResult Index()


{

ViewBag.Usernames = System.IO.File.Exists(filePath) ?
System.IO.File.ReadAllText(filePath) : "No usernames saved yet.";
return View();
}

[HttpPost]
public ActionResult Index(UserName unamemodel)
{
if (ModelState.IsValid)
{

string hashedPassword =
BCrypt.Net.BCrypt.HashPassword(unamemodel.password);

string userData = $"{unamemodel.username} | {hashedPassword}\n";


System.IO.File.AppendAllText(filePath, userData, Encoding.UTF8);

// new
return RedirectToAction("Login");
}

ViewBag.Usernames = System.IO.File.Exists(filePath) ?
System.IO.File.ReadAllText(filePath) : "No usernames saved yet.";
return View(unamemodel);
}

// new
public ActionResult Login()
{
return View();
}

// new
[HttpPost]
public IActionResult Login(string username, string password)
{
if (System.IO.File.Exists(filePath))
{
string[] lines = System.IO.File.ReadAllLines(filePath);

foreach (string line in lines)


{
string[] parts = line.Split(" | ");
if (parts.Length == 2)
{
string storedUsername = parts[0];
string storedHashedPassword = parts[1];

if (storedUsername == username &&


BCrypt.Net.BCrypt.Verify(password, storedHashedPassword))
{
return RedirectToAction("Success");
}
}
}
}

ViewBag.Message = "Invalid username or password.";


return View();
}

public ActionResult Success()


{
return View();
}
}
}

1. Update the RedirectToAction parameter to Login.

return RedirectToAction("Login");

2. Update the ActionResult from Success to Login

public ActionResult Login()


{
return View();
}
3. Create new [HttpPost]

[HttpPost]
public IActionResult Login(string username, string password)

1. [HttpPost] (Attribute)

• This attribute indicates that the method should handle HTTP POST requests.

• It means the Login action is triggered when the form is submitted via the POST
method.

2. public (Access Modifier)

• This specifies that the method is accessible from other parts of the application,
including the client (browser) making a request.

3. IActionResult (Return Type)

• IActionResult is an interface that represents an HTTP response.


• It allows returning different types of responses (e.g., View(), RedirectToAction(),
Json(), etc.).
• In this case, it will likely return a view or redirect based on login success/failure.

4. Login (Method Name)

• This is the name of the action method.

• It will be used in routing (e.g., POST /Username/Login).

5. string username, string password (Method Parameters)

• These parameters receive values from the form submission.


• If the form has input fields named username and password, ASP.NET Core will
automatically bind their values to these parameters.

if (System.IO.File.Exists(filePath))

1. if (Conditional Statement)
• This is a control flow statement that checks whether a condition is true.

• If the condition inside the parentheses evaluates to true, the code inside the if
block executes.
• If it's false, the block is skipped.

2. System.IO (Namespace)

• System.IO is a namespace in C# that provides classes for handling file and


directory operations, such as reading, writing, and checking file existence.

3. File (Class)

• File is a static class inside the System.IO namespace.

• It provides methods to perform operations on files, like ReadAllText(),


WriteAllText(), Delete(), and Exists().
4. Exists(filePath) (Method Call)
• Exists() is a method of the File class that checks whether a file exists at the
specified path.

• It takes a string parameter (filePath), which represents the full path of the file to
check.

• It returns a bool (true if the file exists, false otherwise).

5. filePath (Variable)

• filePath is a variable that stores the location of the file (e.g.,


"C:\\Users\\THOR\\Desktop\\UD-R\\UserCredentials.txt").

• The method checks if a file exists at this path.

string[] lines = System.IO.File.ReadAllLines(filePath);

1. string[] (Data Type - Array of Strings)

• This declares a variable lines that holds an array of strings (string[]).

• Each element in this array represents a single line from the file.
2. lines (Variable Name)

• This is the name of the variable that stores the lines read from the file.

3. = (Assignment Operator)

• Assigns the result of System.IO.File.ReadAllLines(filePath) to the lines variable.


4. System.IO (Namespace)
• System.IO is a namespace in C# that provides functionality for file input and
output operations.

5. File (Class)

• File is a static class inside System.IO that provides various methods for working
with files.

6. ReadAllLines(filePath) (Method Call)

• ReadAllLines() is a method of the File class.


• It takes a string parameter (filePath), which specifies the full path of the file to
read.

• It reads all lines from the file and returns them as an array of strings (string[]),
where each element represents a line in the file.

7. filePath (Variable)
• filePath is a variable that stores the location of the file (e.g.,
"C:\\Users\\THOR\\Desktop\\UD-R\\UserCredentials.txt").
• This is the file from which ReadAllLines() reads data.
foreach (string line in lines) {

1. foreach (Loop Keyword)

o A loop that iterates over each element in a collection (e.g., arrays, lists, or
other iterable objects).

o It simplifies iterating through an array without needing an explicit index.

2. (string line in lines) (Loop Declaration)

o string: Declares that each item in the collection is treated as a string.

o line: A variable that represents the current element in the loop.

o in: A keyword that specifies the collection to iterate over.


o lines: The collection (array of strings) that contains the lines read from the
file.
3. Loop Execution

o The loop starts at the first element of lines.

o On each iteration, line holds the value of the current string in the array.

o The loop moves to the next element until all elements are processed.

string[] parts = line.Split(" | ");

1. string[] (Data Type - Array of Strings)

o Declares parts as an array of strings (string[]).

o Each element in this array will hold a substring extracted from line.

2. parts (Variable Name)


o This is the variable that stores the result of the Split() operation.

o It will contain multiple substrings obtained by splitting line.

3. = (Assignment Operator)

o Assigns the result of line.Split(" | ") to the parts array.

4. line (String Variable)

o line is a string variable that contains text (e.g., a single line from a file).

o This text will be split into smaller parts based on the given delimiter (" | ").
5. .Split(" | ") (Method Call)

o Split() is a method of the string class.

o It splits the line into an array of substrings based on a given delimiter (" |
").

o The delimiter " | " is used as a separator.

o Each part before or after " | " becomes an element in the parts array.
if (parts.Length == 2) {

1. if (Conditional Statement)

o The if keyword starts a conditional statement.

o It evaluates a condition inside parentheses () and executes the block {} if


the condition is true.

2. (parts.Length == 2) (Condition)

o parts.Length: Retrieves the number of elements in the parts array.

o ==: Comparison operator that checks if the left-hand side (parts.Length) is


equal to the right-hand side (2).

o 2: The expected number of elements in the parts array.


o The condition ensures that parts contains exactly two elements,
preventing errors when accessing parts[0] and parts[1].

3. { ... } (Code Block)


o The block of code inside {} runs only if parts.Length == 2 is true.

o Typically, this block processes the extracted username and password from
parts[0] and parts[1].

string storedUsername = parts[0];

1. string (Data Type)

o Declares a variable of type string, which is used to store text.

o string is a sequence of characters in C#.

2. storedUsername (Variable Name)

o This is the name of the variable being declared.

o It holds the extracted username from the parts array.

3. = (Assignment Operator)
o Assigns the value on the right (parts[0]) to the variable storedUsername.

4. parts[0] (Array Element Access)

o parts is an array containing the split components of a string (from


line.Split(" | ")).

o parts[0] accesses the first element of the array, which is expected to be


the stored username.

string storedHashedPassword = parts[1];

1. string (Data Type)


o Declares a variable of type string, which is used to store text data.
o In this case, it holds the hashed password retrieved from the parts array.

2. storedHashedPassword (Variable Name)

o This is the name of the variable that will store the hashed password.

o It is descriptive, indicating that it holds the stored hashed version of a


password.

3. = (Assignment Operator)

o Assigns the value from the right-hand side (parts[1]) to the variable
storedHashedPassword.

4. parts[1] (Array Element Access)


o parts is an array that contains the split components of a string (from
line.Split(" | ")).

o parts[1] retrieves the second element of the array, which is expected to be


the hashed password.

if (storedUsername == username && BCrypt.Net.BCrypt.Verify(password,


storedHashedPassword))

Explanation:

1. if (Conditional Statement)

o This keyword is used to evaluate a condition.

o If the condition inside the parentheses ( ) evaluates to true, the code


inside the if block executes.

2. storedUsername == username (String Comparison)

o storedUsername is the username retrieved from the stored credentials.

o username is the input username provided by the user.

o == checks if both strings are equal (case-sensitive comparison).

o If the usernames match, this part of the condition evaluates to true.


3. && (Logical AND Operator)

o Ensures that both conditions must be true for the entire if condition to be
true.

o If either storedUsername == username or BCrypt.Verify(password,


storedHashedPassword) is false, the if condition will not execute.
4. BCrypt.Net.BCrypt.Verify(password, storedHashedPassword) (Password
Verification)
o This method checks if the input password matches the stored
storedHashedPassword.

o password: The plaintext password entered by the user.


o storedHashedPassword: The hashed password retrieved from the file.

o BCrypt.Verify hashes password and compares it with


storedHashedPassword.
o If the hashed versions match, this method returns true; otherwise, it
returns false.

return RedirectToAction("Success");

1. return (Keyword)

o Exits the current method and returns a result.

o In this case, it returns an IActionResult, which is a response in an


ASP.NET MVC controller.

2. RedirectToAction("Success") (Method Call)

o This is a built-in ASP.NET Core MVC method that redirects the user to a
different action method within the same controller.

o "Success" is the name of the action method being redirected to.

o This means that after form submission, the user is redirected to the
Success action, which likely renders a confirmation page.

ViewBag.Message = "Invalid username or password.";


return View();
}

public ActionResult Success()


{
return View();
}

You might also like