User Login FormsAuthentication in Cookies MVC 有關驗證以及Cookies
雖然都是程式碼但請實作一次。
首先建立Model
將登入畫面所使用的model 以及驗證所需的model Princaipal
放在一起。
public class VMLoginModel
{
// 登入帳號
[Required(ErrorMessage = "請輸入帳號")]
[EmailAddress]
[Display(Name = "ID")]
public string Account { get; set; }
// 登入密碼
[Required(ErrorMessage = "請輸入密碼")]
[Display(Name = "Password")]
[DataType(DataType.Password)]
public string Password { get; set; }
}
//登入所需要驗證資料 Model
public class UserPrincipal : IPrincipal
{
public UserPrincipal(IIdentity identity)
{
Identity = identity;
}
public IIdentity Identity
{
get;
private set;
}
public VMLoginModel User { get; set; }
public bool IsInRole(string role)ㄋ
{
return true;
}
}
Create UserInfoSession 裡面放使用者存放Session
public class UserInfoSession
{
// 使用者帳號
public string UserID { get; set; }
// 使用者key值
public int Userindx { get; set; }
// 使用者員編
public string Usercn { get; set; }
}
建立 Class UserAuthentication 放置 User FormsAuthenticationTicket的相關資訊
public static bool ValidateUser(VMLoginModel logon, HttpResponseBase response)
{
bool result = false;
if (Membership.ValidateUser(logon.Account, logon.Password))
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
//取得使用者個人資料
string userData = serializer.Serialize(User);
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1,
logon.Account,
DateTime.Now,
DateTime.Now.AddHours(3),
true,
userData,
FormsAuthentication.FormsCookiePath
);
//建立加密 表單驗證票證 Encrypt the ticket.
string encTicket = FormsAuthentication.Encrypt(ticket);
// Create the cookie.
response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));
//驗證通過
result = true;
}
return result;
}
使用者資料 是否通過驗證
public static VMLoginModel User
{
get
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
// The user is authenticated. Return the user from the forms auth ticket.
return ((UserPrincipal)(HttpContext.Current.User)).User;
}
else if (HttpContext.Current.Items.Contains("User"))
{
// The user is not authenticated, but has successfully logged in.
return (VMLoginModel)HttpContext.Current.Items["User"];
}
else
{
return null;
}
}
}
從資料庫抓取資料
public static VMLoginModel AuthenticateUser(string username, string password)
{
VMLoginModel user = new VMLoginModel();
// Lookup user in database, web service, etc. We'll just generate a fake user for this demo.
驗證 cookie
//http://www.primaryobjects.com/2012/12/07/mvc-forms-authentication-and-storing-data-in-the-cookie/
IEnumerable<Table> modellist = Enumerable.Empty<Table>();
DynamicParameters param = new DynamicParameters();
param.Add("@id", username, System.Data.DbType.String, System.Data.ParameterDirection.Input, 1024);
param.Add("@pwd", password, System.Data.DbType.String, System.Data.ParameterDirection.Input, 1024);
//查詢名單是否正確
modellist = DbHelper.Query<Table>(null, param);
if (modellist != null && modellist.Count() == 1)
{
HttpContext.Current.Session["member_id"] = modellist.FirstOrDefault().id;
HttpContext.Current.Session["cn"] = modellist.FirstOrDefault().cn;
HttpContext.Current.Session["indx"] = modellist.FirstOrDefault().indx;
HttpContext.Current.Session["roles"] = modellist.FirstOrDefault().groups;
HttpContext.Current.Session["realname"] = modellist.FirstOrDefault().realname;
HttpContext.Current.Session["company"] = modellist.FirstOrDefault().company;
HttpContext.Current.Session["groups"] = modellist.FirstOrDefault().manager;
//這個RedirectFromLoginPage功能會 自動存cookie 並 自動導回ReturnURL指定的頁面
FormsAuthentication.RedirectFromLoginPage(modellist.FirstOrDefault().id, true);
user.Account = modellist.FirstOrDefault().id;
user.key = modellist.FirstOrDefault().indx;
user.Password = modellist.FirstOrDefault().pwd;
}
else
{
//當帳號密碼發生錯誤 所需要顯示錯誤訊息在前端頁面上
user = null;
}
return user;
}
//登出機制會清除session 以及 FormCokkieName
public static void Logoff(HttpSessionStateBase session, HttpResponseBase response)
{
// Delete the user details from cache.
session.Abandon();
//clear all session
session.RemoveAll();
// Delete the authentication ticket and sign out.
FormsAuthentication.SignOut();
// Clear authentication cookie.
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, "");
cookie.Expires = DateTime.Now.AddYears(-1);
response.Cookies.Add(cookie);
}
建立UserProvider
因要使用MembershipProvider UserProvider:MembershipProvider
public override bool ValidateUser(string username, string password)
{
// Check if this is a valid user.
VMLoginModel user = UserAuthentication.AuthenticateUser(username, password);
if (user != null)
{
// Store the user temporarily in the context for this request.
HttpContext.Current.Items.Add("User", user);
return true;
}
else
{
return false;
}
}
public override MembershipUser GetUser(string username, bool userIsOnline)
{
if (UserAuthentication.User != null)
{
return new MembershipUser("UserMembershipProvider", username,
UserAuthentication.User.key, UserAuthentication.User.Account, null,null, true, false, DateTime.MinValu e, DateTime.MinValue,DateTime.MinValue, DateTime.MinValue, DateTime.MinValue);
}
else
{
return null;
}
}
接下來請在Global.asax
裡建立
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
//取的 Form 認證 目前這位使用者身分
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
//給予使用者 驗證身分
GenericIdentity identify = new GenericIdentity(authTicket.Name, "Forms");
UserPrincipal principal = new UserPrincipal(identify);
//取得使用者加密資料
string userData = ((FormsIdentity)(Context.User.Identity)).Ticket.UserData;
// Deserialize the json data and set it on the custom principal.
JavaScriptSerializer serializer = new JavaScriptSerializer();
//解密使用者資料
principal.User = (VMLoginModel)serializer.Deserialize(userData, typeof(VMLoginModel));
Context.User = principal;
}
}
最後最重要請注意要在Web.config設定Membership 請注意 UserProvider 請自行開一隻cs 否則會load不到
<membership defaultProvider="UserProvider">
<providers> <clear/>
name 是用來做識別用的,同時可能有好幾個會員提供者。
type 包含會員提供者的名稱空間 類名稱 及組件名稱。
Provide 要另外放
<add name="UserProvider" type="Providers.UserProvider"/>
</providers>
</membership>
登入驗證的導向動作 尚未驗證通過就直接導到登入畫面
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" defaultUrl ="~/Home/XXX" name=".YourApplication" timeout="60" cookieless="AutoDetect" />
</authentication>
重點來了剛驗證完成後若所有的acton都要驗證請掛上[Authorize]
可以直接丟到Class級對所有的Action的驗證
跟System.Web.Security.FormsAuthentication.RedirectFromLoginPage(strUsername, true);
做搭配使用
Ex:
[Authorize]
public class SettingsController : Controller