以 Cookie 實作 ASP.NET Core 登入功能
登入功能是很常會遇到的需求,但往往要實作時都不知從何著手,其中一個原因它有一些設定上的步驟,通常做過一次就忘了,本篇文章就以最簡單的 Cookie 驗證做示範 (以 ASP.NET Core 專案為例)
一開始先實作驗證用的 Manager 類別
public class PersonModel
{
[DisplayName("姓名")]
public string Name { get; set; } = string.Empty;
[DisplayName("手機")]
public string Phone { get; set; } = string.Empty;
[DisplayName("Email")]
public string Email { get; set; } = string.Empty;
[DisplayName("生日")]
public DateTime? Birthday { get; set; } = null;
}
public interface IAuthManager
{
bool AuthByNameAndPassword(string username, string password, out PersonModel person);
PersonModel? GetPersonByName(string username);
}
public class AuthManager : IAuthManager
{
private ConcurrentDictionary<string, string> _authData;
private ConcurrentDictionary<string, PersonModel> _users;
public AuthManager()
{
_authData = new ConcurrentDictionary<string, string>();
_authData.TryAdd("peter", "1234");
_authData.TryAdd("john", "1234");
_users= new ConcurrentDictionary<string, PersonModel>();
_users.TryAdd("peter", new PersonModel
{
Name = "Peter",
Birthday = new DateTime(1980, 6, 5),
Email = "peter@gmail.com",
Phone = "0922000000"
});
_users.TryAdd("john", new PersonModel
{
Name = "john",
Birthday = new DateTime(1990, 5, 5),
Email = "john@gmail.com",
Phone = "0922000000"
});
}
public bool AuthByNameAndPassword(string username, string password, out PersonModel person)
{
bool result = false;
person = new PersonModel();
if(_authData.ContainsKey(username))
{
if (_authData[username] == password)
{
result = true;
person = _users[username];
}
}
return result;
}
public PersonModel? GetPersonByName(string username)
{
PersonModel? person = null;
if (_authData.ContainsKey(username))
{
person = _users[username];
}
return person;
}
}
再來是 Program.cs 上的設定
//auth
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(option =>
{
option.LoginPath = "/Home/Login";
});
builder.Services.AddAuthorization();
builder.Services.AddTransient<IAuthManager, AuthManager>();
app.UseAuthentication();
app.UseAuthorization();
然後是 Home Controller 上的實作
[HttpGet]
public IActionResult Login()
{
return View();
}
[HttpPost]
public IActionResult Login(LoginModel model)
{
if (!_authManager.AuthByNameAndPassword(model.UserName, model.Password, out PersonModel person))
{
return RedirectToAction("Login");
}
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, model.UserName),
new Claim("email", person.Email),
};
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
var authProperties = new AuthenticationProperties
{
ExpiresUtc = DateTimeOffset.UtcNow.AddHours(3),
IsPersistent = true
};
var _= HttpContext.SignInAsync(new ClaimsPrincipal(claimsIdentity), authProperties);
return RedirectToAction("Info");
}
[Authorize]
public IActionResult Info()
{
var data = HttpContext.User.Claims.First();
string name = data.Value;
PersonModel? person = _authManager.GetPersonByName(name);
return View(person);
}
在需要登入的 Action 上加入 Authorize 即可
而登入的方法也很簡單,呼叫 await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme)
就可以了
參考資料