【问题标题】:Why isn't my cookie being removed?为什么我的 cookie 没有被删除?
【发布时间】:2015-12-10 20:39:10
【问题描述】:

我正在尝试在用户登录时创建一个持久性 cookie(不使用内置身份验证)。

我能想到的唯一方法是创建一个过期日期设置为DateTime.Now.AddYears(1)的cookie

因为我想允许用户注销,所以我在登录表单后面的每个页面的布局上都有一个注销按钮。

此注销按钮如下所示:

<li>@Html.ActionLink("Log Out", "Logout", "Home")</li>

让我感到困惑的是,这段代码并没有从浏览器中删除 cookie。它会将我带回登录表单,但我仍然可以轻松导航回受保护的页面,并且它仍会根据我之前的登录记录记住我的身份。

这是我的代码:

    [AllowAnonymous]
    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Login(User model)
    {
        try
        {
            DoLogin(model.EmailAddress, model.Password);
            return Json(new
            {
                Message = "Success",
                IsOK = bool.TrueString
            });
        }
        catch (Exception ex)
        {
            SendError("/", ex);
            return ReportError(ex, "USER LOGIN");
        }
    }

    private void DoLogin(string EmailAddress, string Password)
    {
        var user = db.Users.Include("UserRole").FirstOrDefault(x => x.EmailAddress == EmailAddress);

        if (Hashing.ValidatePassword(Password, user.Password))
            generateCookie(user);
    }

    private void generateCookie(Models.User u)
    {
        HttpCookie userCookie = new HttpCookie("Ortund");
        userCookie.Values["userid"] = Convert.ToString(u.Id);
        userCookie.Values["fname"] = u.FirstName;
        userCookie.Values["lname"] = u.LastName;
        userCookie.Values["role"] = u.UserRole.RoleName;
        userCookie.Expires = DateTime.Now.AddYears(1);
        Response.Cookies.Add(userCookie);
    }

那为什么不清除我的 cookie?

编辑

所以现在我已经根据问题答案中的建议修改了我的代码(见下文)。

我在控制器上添加了一个注销操作,它会这样做:

    public ActionResult Logout()
    {
        Session.Clear();
        HttpCookie userCookie = new HttpCookie("Ortund");
        userCookie.Expires = DateTime.Now.AddYears(-1);
        Response.Cookies.Add(userCookie);

        return View("Index");
    }

虽然我的登录似乎仍然可以正常工作,但 Request Cookie 并未使用新的登录详细信息进行更新。这是我登录后的样子:

    Request.Cookies["Ortund"] {System.Web.HttpCookie} System.Web.HttpCookie  
    Domain null string  
    Expires {0001-01-01 12:00:00 AM} System.DateTime  
    HasKeys true bool  
    HttpOnly false bool  
    Name "Ortund" string  
    Path "/" string  
    Secure false bool  
    Shareable false bool

【问题讨论】:

  • 1.您需要将过期的cookie写入响应,而不是读取并将其设置回请求。 2. FormsAuthentication.SignOut() 可能会或可能不会删除 cookie,这取决于您如何在 web.config 中配置表单身份验证。查看您的代码,您可能没有正确配置。
  • @Igor 实际上我根本没有设置表单身份验证,所以我想我可以把它拿出来吧
  • 顺便说一句,使用action 作为查询字符串变量可能会有点混乱,因为术语操作在 MVC 中具有特定含义。为什么不创建一个实际的 Logout 操作来执行 cookie 失效,然后重定向到 Index 操作?

标签: asp.net asp.net-mvc cookies


【解决方案1】:

你需要将过期的cookie写入Response,而不是读取并设置回Request。

var cookie = Request.Cookies["Ortund"];
cookie.Expires = DateTime.Now.AddSeconds(-1);
Response.Cookies.Add(cookie);

我会阅读how to implement Forms Authentication in c#。这将为您提供一个更好的起点,然后尝试滚动您自己的身份验证 cookie,这将导致安全漏洞。标准表单身份验证已经提供了很多东西和一个简单的 API 来访问它,包括加密票证、提供身份信息等的方法。

您也可以查看asp.net identity。这是 Microsoft 用于管理身份和提供身份验证和授权的最新 API。它还与 SSO 集成,例如使用 Facebook 或 Microsoft 身份存储对用户进行身份验证。

编辑 - 根据要求提供更多信息

这里是一些使用基本内置 asp.net 表单身份验证的示例代码。此示例基于 cookie。您还需要配置 web.config 以使用它。完成此操作后,其余部分会自动发生,您可以随时使用HttpContext.User.Identity. 获取用户信息。在 web.config 中,您还需要添加解密和验证密钥。

public sealed class AuthController : Controller
{
    [AllowAnonymous] // get the view to login
    public ActionResult Login()
    {
        return View();
    }
    [HttpPost]
    [AllowAnonymous] // execute a login post
    public ActionResult ExecuteLogin(LoginModel model)
    {
        // validate credentials
        var ticket = new FormsAuthenticationTicket(1, model.UserName, DateTime.Now, DateTime.Now.AddHours(3), model.RememberMe, /*anything else you want stored in the ticket*/ null);
        var encryptedTicket = FormsAuthentication.Encrypt(ticket);
        var isSsl = Request.IsSecureConnection; // if we are running in SSL mode then make the cookie secure only

        var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
        {
            HttpOnly = true, // always set this to true!
            Secure = isSsl,
        };

        if (model.RememberMe) // if the user needs to persist the cookie. Otherwise it is a session cookie
            cookie.Expires = DateTime.Today.AddMonths(3); // currently hard coded to 3 months in the future

        Response.Cookies.Set(cookie);

        return View(); // return something
    }
    [Authorize] // a secured view
    public ActionResult SecuredView() {
        return View();
    }
    [Authorize] // log the user out
    public ActionResult Logout()
    {
        System.Web.Security.FormsAuthentication.SignOut();
        return RedirectToAction("Index", "Home");
    }
}

这是 web.config 更改

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
... 
  <system.web>
    <authentication mode="Forms">
      <forms name="myAuthCookie" ticketCompatibilityMode="Framework40" cookieless="UseCookies" requireSSL="false" timeout="180" protection="Encryption" />
    </authentication>
    <machineKey decryption="AES" decryptionKey="key here" validation="HMACSHA256" validationKey="validation key here" />
  </system.web>
</configuration>

【讨论】:

  • Igor,如果您可以查看问题以查看新的编辑并帮助解决问题,我将不胜感激
  • @Ortund 我不会推出你自己的安全性,这是个坏主意。症状是 cookie 过期标志的处理方式因接收它的浏览器而异。从技术上讲,浏览器可能会完全忽略该值而不做任何事情。同样,我强烈建议您查看 Microsoft 已经实施的表单身份验证控件。它可以在 web.config 中进行配置,您可以使用 cookie 来保存用户经过身份验证的状态和身份。当您使用他们的机制使会话过期时,您可以保证会话现在无效。
  • @Ortund - 我添加了一个示例,您可以使用 asp.net 中包含的基本 api 进行身份验证。
【解决方案2】:

您需要将cookie再次写入浏览器

HttpCookie userCookie = new HttpCookie("Ortund");
userCookie.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(userCookie);

不仅如此

Request.Cookies["Ortund"].Expires = DateTime.Now.AddSeconds(1);

一个很好的解释为什么,it's in my own answer 来自同一时间......

【讨论】:

  • Mkay 所以当我检查用户是否有一个有效的 cookie 时,很明显检查 if (Request.Cookies["Ortund"] != null) { // show the secure stuff } 将不起作用,因为 cookie 仍然存在......那么我该如何验证呢?
  • 只需在注销时删除cookie,但您仍然需要写入 cookie,而不仅仅是更改Expiry 属性。顺便说一句,如果我知道 cookie 名称,我总是可以在浏览器中创建它并登录,甚至不知道用户名或密码......小心你在做什么......(你不知道'甚至不编码值...)
  • 请再看看这个问题。我现在遇到 cookie 问题 - 当我再次尝试登录时 cookie 值没有改变
猜你喜欢
  • 2012-09-22
  • 1970-01-01
  • 2010-10-12
  • 1970-01-01
  • 2016-02-14
  • 1970-01-01
  • 2013-05-22
  • 2013-02-25
  • 1970-01-01
相关资源
最近更新 更多