没有 SetAuthCookie() 的自定义 MVC 身份验证

Custom MVC Authentication without SetAuthCookie()

由于我的项目要求,我想为我的 MVC 控制器操作提供自定义身份验证。因此,我不会使用 SetAuthCookie()。

最初我设置了一个cookie如下;

string userData = EncDec.MakeString(user.Email + "|" + user.UserId);

//the Cookie and FormsAuthenticationTicket expiration date/time is the same
DateTime cookieExpiry = DateTime.Now.AddMinutes(AccountPage.MvcApplication.COOKIE_EXPIRY_MINUTES);

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
          1,                                     // ticket version
          user.UserName,                         // authenticated username
          DateTime.Now,                          // issueDate
          cookieExpiry,                          // expiryDate
          false,                                 // true to persist across browser sessions
          userData,                              // can be used to store additional user data
          FormsAuthentication.FormsCookiePath);  // the path for the cookie

string encryptedTicket = FormsAuthentication.Encrypt(ticket);

//create the cookie
HttpCookie cookie = new HttpCookie("ADV_" + Extensions.ControllerExtensionMethods.GetGuid(this), encryptedTicket);
cookie.Secure = true;
cookie.HttpOnly = true;
cookie.Expires = cookieExpiry;
Response.Cookies.Add(cookie);

HttpCookie 与加密的 FormsAuthenticationTicket 一起保存在客户端浏览器中。

然后在我的控制器操作中,每当我需要检查并验证用户是否已通过身份验证时,我都会调用此方法;

public static FormsAuthenticationTicket IsAuthenticated(string guid)
{
     HttpCookie cookie = HttpContext.Current.Request.Cookies["ADV_" + guid];

     if (cookie != null)
     {
           string encryptedTicket = cookie.Value;
           FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(encryptedTicket);

            if (!ticket.Expired)
            {
               //if the user is authenticated and the cookie hasn't expired we increase the expiry of the cookie - keep alive
               DateTime cookieExpiry = DateTime.Now.AddMinutes(AccountPage.MvcApplication.COOKIE_EXPIRY_MINUTES);

               //create a new ticket based on the existing one
               FormsAuthenticationTicket newTicket = new FormsAuthenticationTicket(
                      ticket.Version,                        // ticket version
                      ticket.Name,                           // authenticated username
                      ticket.IssueDate,                      // issueDate
                      cookieExpiry,                          // expiryDate, changed to keep alive if user is navigating around site
                      false,                                 // true to persist across browser sessions
                      ticket.UserData,                       // can be used to store additional user data
                      ticket.CookiePath);                    // the path for the cookie

               string newEncryptedTicket = FormsAuthentication.Encrypt(newTicket);

               //keep alive
               HttpCookie newCookie = new HttpCookie("ADV_" + guid, newEncryptedTicket);
               newCookie.Secure = true;
               newCookie.HttpOnly = true;
               newCookie.Expires = cookieExpiry;

               HttpContext.Current.Response.Cookies.Set(newCookie);

               return newTicket;
          }
     }

            return null; 
}

每次重新验证用户时,我都会增加 cookie 过期的时间,以便登录保持活动状态。

一切似乎都正常,并且用户已正确通过身份验证,如果他们未通过身份验证,我会将他们重定向到登录页面,如果他们也未通过身份验证,他们将无法访问方法。

我的问题是:

  1. 这种处理身份验证的方式安全吗?
  2. 在安全风险方面,有什么我应该注意的吗?

谢谢。

您基本上需要查看创建自定义身份验证属性。

我不打算在这里提供实际的实现,但这会让你走上正确的道路。

这是基本表示:-

 public class GoogleAuthAttribute : FilterAttribute, IAuthenticationFilter
    {
        public void OnAuthentication(AuthenticationContext filterContext)
        {

            IIdentity ident = filterContext.Principal.Identity;

            if (!ident.IsAuthenticated || !ident.Name.EndsWith("@google.com"))
            {
                filterContext.Result = new HttpUnauthorizedResult();
            }
        }

        public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
        {
            if (filterContext.Result == null || filterContext.Result is HttpUnauthorizedResult)
            {
                filterContext.Result =
                    new RedirectToRouteResult(new RouteValueDictionary
                    {
                        {"controller", "GoogleAccount"},
                        {"action", "Login"},
                        {"returnUrl", filterContext.HttpContext.Request.RawUrl}
                    });
            }

        }
    }

我是从我目前正在阅读的关于 MVC5 的 Apress 书中摘录的。如果 OnAuthentification 失败,您设置 AuthenticationContext 的结果 属性,然后将其传递给 AuthenticationChallengeContext,您可以在其中添加您的质询代码。

在我的示例中,用户被重定向到登录页面。

您需要做的就是将此 AuthentificationAttribute 放在您需要的操作方法上。

您应该能够在其中构建或使用您的客户安全代码。

您真的应该问问自己,添加自定义安全措施是否是个好主意,因为它可能会导致您想要的更多问题。