=x= 🌵 Sign In page 後台登入密码验证。
📌 使用者於登入页面输入帐号及密码送出後,後端会依取得帐号连进资料库比对,如果帐号不存在,就送出帐号不存在的说明,如果帐号存在,就取出该帐号 "密码加盐加密结果" + "盐的内容",再将取出的 "盐的内容" 与登入页输入的密码又一次进行 hash 杂凑加密,最後将加密後的结果比对资料库取出的 "密码加盐加密结果",如果比对不相同,就送出密码错误的说明,如果比对相同就进行跳转页面,登入成功。
🧠 密码如果验证成功会一并发出 FormsAuthenticationTicket 验证票,验证票可用来进行权限的识别导引,以及再後台操作时保持登入状态,以下程序码会一并呈现使用方式。
👀 验证与授权必读好文1 : 简介 ASP.NET 表单验证 (FormsAuthentication) 的运作方式
👀 验证与授权必读好文2 : [ASP.NET] Forms 验证与授权
<configuration>
<system.web>
<authentication mode="Forms"></authentication>
</system.web>
</configuration>
// Argon2 验证加密密码
// Hash 处理加盐的密码功能
private byte[] HashPassword(string password, byte[] salt)
{
var argon2 = new Argon2id(Encoding.UTF8.GetBytes(password));
//底下这些数字会影响运算时间,而且验证时要用一样的值
argon2.Salt = salt;
argon2.DegreeOfParallelism = 8; // 4 核心就设成 8
argon2.Iterations = 4; //迭代运算次数
argon2.MemorySize = 1024 * 1024; // 1 GB
return argon2.GetBytes(16);
}
//验证
private bool VerifyHash(string password, byte[] salt, byte[] hash)
{
var newHash = HashPassword(password, salt);
return hash.SequenceEqual(newHash); // LINEQ
}
//设定验证票
private void SetAuthenTicket(string userData, string userId)
{
//宣告一个验证票 //需额外引入 using System.Web.Security;
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, userId, DateTime.Now, DateTime.Now.AddHours(3), false, userData);
//加密验证票
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
//建立 Cookie
HttpCookie authenticationCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
//将 Cookie 写入回应
Response.Cookies.Add(authenticationCookie);
}
AddHours
要配合使用情境设定,使用者切换页面时可以保持登入状态。protected void Button1_Click(object sender, EventArgs e)
{
string password = TextBox2.Text;
// 1.连线资料库
SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
// 2.sql语法 (@参数化避免隐码攻击)
string sql = "SELECT * FROM managerData WHERE account = @account";
// 3.创建 command 物件
SqlCommand command = new SqlCommand(sql, connection);
// 4.放入参数化资料
command.Parameters.AddWithValue("@account", TextBox1.Text);
// 5.资料库用 Adapter 执行指令
SqlDataAdapter dataAdapter = new SqlDataAdapter(command);
// 6.建立一个空的 Table
DataTable dataTable = new DataTable();
// 7.将资料放入 Table
dataAdapter.Fill(dataTable);
// 登入流程管理 (Cookie)
if (dataTable.Rows.Count > 0) {
// SQL 有找到资料时执行
//将字串转回 byte
byte[] hash = Convert.FromBase64String(dataTable.Rows[0]["password"].ToString());
byte[] salt = Convert.FromBase64String(dataTable.Rows[0]["salt"].ToString());
//验证密码
bool success = VerifyHash(password, salt, hash);
if (success) {
//宣告验证票要夹带的资料 (用;区隔)
string userData = dataTable.Rows[0]["maxPower"].ToString() + ";" + dataTable.Rows[0]["account"].ToString() + ";" + dataTable.Rows[0]["name"].ToString() + ";" + dataTable.Rows[0]["email"].ToString();
//设定验证票(夹带资料,cookie 命名) // 需额外引入using System.Web.Configuration;
SetAuthenTicket(userData, TextBox1.Text);
//导页至权限分流页
Response.Redirect("CheckAccount.ashx");
}
else {
//资料库里找不到相同资料时,表示密码有误!
Label4.Text = "password error, login failed!";
Label4.Visible = true;
connection.Close();
return;
}
}
else {
//资料库里找不到相同资料时,表示帐号有误!
Label4.Text = "Account error, login failed!";
Label4.Visible = true;
//终止程序
//Response.End(); //会清空页面
return;
}
connection.Close();
}
📢 因为使用 Argon2 验证会增加运算时间,跳转页面会有延迟,建议在 .aspx 页面用 JavaScript 监听按钮加入验证中的 CSS 盖版动画,另外登入页可增加一按钮当成返回前台首页的功能,权限分流页使用 .ashx (泛型处理常式)制作,在後续页面会一并介绍相关设定及功能。
🧂 要使密码更安全的作法,其实还要加"安全盐"或称作"胡椒",因为盐会和加密後的密码一起放在资料库,如果资料库被攻击就可能会被破解,"胡椒"需要另外存放来达到提升安全性的效果,或是把它写在程序里,这样至少也是放在不同地方。
👀 胡椒的使用方式 : How to apply a pepper correctly to bcrypt?
👀 胡椒的维基百科 : Pepper (cryptography)
<<: [Day14] Vite 出小蜜蜂~ Game Logic - Sequential Movement!
写在前面 placeholder for d10 placeholder for d10 place...
双指针算是一个解题蛮常用的小技巧,双指针指的是用两个指针对整个资料做遍历,而双指针又依照移动的方向...
上竞技场就是要决斗阿,不然要干嘛。 来让人物发射武器!血流成河吧! 首先来回顾一下 D27 武器规划...
2022 新的一年降临了,回首望望过去,原本用 Blog 方式写下技术文, 後来尝试用 youtub...
随着时间资料累积久都会有占空间与查询不易的问题,在Mysql的日志中常用的error log 和 s...