Forms Authentication 再紀錄
MVC5, FormsAuthentication 再紀錄。
需求
SSO登入。
登入後更換Session。
使用
Forms Authentication
。登出後更換Session。
設定Web.Config驗證模式為:Forms
<configuration>
<system.web>
<authentication mode="Forms">
<forms loginUrl="~/Home/Index" timeout="30" requireSSL="true" />
<!-- timeout 預設:30分鐘; 2880分鐘 = 2天; 8640分鐘 = 6天 -->
<!-- requireSSL,預設:false; 上線再設為true,開發期設為false -->
</authentication>
</system.web>
</configuration>
程式碼紀錄登入與登出
using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using System.Web.SessionState;
namespace YourProject.Controllers
{
public class AccountController : Controller
{
/// 本例為SSO登入。驗 signonKey 並取得授權資料
[HttpGet]
public ActionResult SSO(string id /* signonKey */)
{
//# 模擬登入驗證與取得授權資料
// 一般是登入帳密檢查與取得授權資料,本例為SSO登入。
AuthInfo auth = SimsLogonWithSSO(id);
// userInfo, roles, funcList, authToken
#region 驗證後登入前(註記)更換 Session。
var manager = new SessionIDManager();
string oldSessionId = this.Session.SessionID;
string newSessionId = manager.CreateSessionID(System.Web.HttpContext.Current);
bool redirected, isAdded;
manager.SaveSessionID(System.Web.HttpContext.Current, newSessionId, out redirected, out isAdded);
/// ※更探Session同時,基本上全部暨有的會話資料(session, cookie,etc.)全部不見!
#endregion
// 計算出門票,不讓ticket流向前端。
// ※利用newSessionId的長亂數字串,再加上日期或主機資訊算出唯一性的ticket。
string authTicket = $"{DateTime.Today.GetHashCode().ToString("x")}{newSessionId}";
// 將AuthInfo暫存入AppDomain。
AppDomain.CurrentDomain.SetData(authTicket, auth);
//※ 導向新頁面這樣新Session才有效。
return RedirectToAction("SSO2");
}
/// 將授權資料存入新 Session 並製作 FormsAuthentication cookie 與啟用。
[HttpGet]
public ActionResult SSO2()
{
try
{
#region ## 取得成功驗證資料
// 計算出門票,不讓ticket流向前端。
string authTicket = $"{DateTime.Today.GetHashCode().ToString("x")}{Session.SessionID}";
// 將AuthInfo從AppDomain取出
AuthInfo auth = (AuthInfo)AppDomain.CurrentDomain.GetData(authTicket);
// AppDomain取出值後清空
AppDomain.CurrentDomain.SetData(Session.SessionID, null);
#endregion
#region ## 註記入 Session
Session.Clear();
Session["AuthInfo"] = auth;
// Session["LoginAuthToken"] = authToken;
// Session["LoginUserInfo"] = loginUser;
// Session["LoginUserMenu"] = menuInfo;
#endregion
#region ## 寫入 FormsAuthentication cookie --- 客制化
/// 將使得 @Request.IsAuthenticated == true ;
/// 將使得 [Authorize] 有作用
string userData = "This is the user's private data or authToken, and will been encrypted";
bool isPersistent = false; // (rememberMe == "yes"); // 記住我/永續性
DateTime issueDate = DateTime.Now;
DateTime expiresDate = issueDate.Add(FormsAuthentication.Timeout);
//# auth ticket
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
2,
auth.userId,
issueDate,
expiresDate, // ticket 到期日
isPersistent, //永續性
userData, // 加入客制化資料
FormsAuthentication.FormsCookiePath
);
//# new auth cookie
string encTicket = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket)
{
Secure = FormsAuthentication.RequireSSL,
Expires = isPersistent ? DateTime.MinValue : expiresDate, // cookie 到期日
HttpOnly = true
};
//# 寫入auth cookie,客制化用
Response.Cookies.Add(cookie);
#endregion
// return home page;
TempData["ErrMsg"] = new ErrMsg { errType = ErrTypeEnum.Success, errMsg = "SSO驗證成功。" };
return RedirectToAction("Index", "Home");
}
catch (Exception ex)
{
// 失敗處理…
TempData["ErrMsg"] = new ErrMsg { errType = ErrTypeEnum.Exception, errMsg = "SSO驗證失敗!", exception = ex };
return RedirectToAction("Index", "Home");
}
}
public ActionResult Logout()
{
//clear session &cookie
Response.Cookies.Clear();
Session.Clear();
Session.Abandon();
Session.RemoveAll();
//※ 將會清掉己知所有『連線訊息』包含TempData也是。
// sign out
FormsAuthentication.SignOut();
// 登出後更換 Session
var manager = new SessionIDManager();
string oldSessionId = this.Session.SessionID;
string newSessionId = manager.CreateSessionID(System.Web.HttpContext.Current);
bool redirected, isAdded;
manager.SaveSessionID(System.Web.HttpContext.Current, newSessionId, out redirected, out isAdded);
return View();
//return RedirectToAction("Index", "Home"); // 回首頁
}
}
}
Last updated