【问题标题】:How to store custom data in ASP.NET Membership Cookie如何在 ASP.NET Membership Cookie 中存储自定义数据
【发布时间】:2010-07-14 06:42:36
【问题描述】:

谁能给我一个关于如何在 ASP.NET Membership cookie 中存储自定义数据的示例(或指出正确的方向)?

我需要向 cookie 添加一些自定义属性,例如 UserID 和 URLSlug,并且能够以与检索用户名相同的方式检索信息。

编辑:

我使用了 Code Poet 的示例并提出了以下内容。

当我在Dim SerializedUser As String = SerializeUser(userData) 设置断点时,userData 的值是正确的。它具有我期望它具有的所有属性。

我现在遇到的问题是当我到达Dim userdata As String = authTicket.UserData(断点)时,值是""。我很想弄清楚我做错了什么。

这是代码。

Imports System
Imports System.Web
Imports System.Web.Security

Namespace Utilities.Authentication
    Public NotInheritable Class CustomAuthentication
        Private Sub New()
        End Sub

        Public Shared Function CreateAuthCookie(ByVal userName As String, ByVal userData As Domain.Models.UserSessionModel, ByVal persistent As Boolean) As HttpCookie

            Dim issued As DateTime = DateTime.Now
            ''# formsAuth does not expose timeout!? have to hack around the
            ''# spoiled parts and keep moving..
            Dim fooCookie As HttpCookie = FormsAuthentication.GetAuthCookie("foo", True)
            Dim formsTimeout As Integer = Convert.ToInt32((fooCookie.Expires - DateTime.Now).TotalMinutes)

            Dim expiration As DateTime = DateTime.Now.AddMinutes(formsTimeout)
            Dim cookiePath As String = FormsAuthentication.FormsCookiePath

            Dim SerializedUser As String = SerializeUser(userData)

            Dim ticket = New FormsAuthenticationTicket(0, userName, issued, expiration, True, SerializedUser, cookiePath)
            Return CreateAuthCookie(ticket, expiration, persistent)
        End Function

        Public Shared Function CreateAuthCookie(ByVal ticket As FormsAuthenticationTicket, ByVal expiration As DateTime, ByVal persistent As Boolean) As HttpCookie
            Dim creamyFilling As String = FormsAuthentication.Encrypt(ticket)
            Dim cookie = New HttpCookie(FormsAuthentication.FormsCookieName, creamyFilling) With { _
             .Domain = FormsAuthentication.CookieDomain, _
             .Path = FormsAuthentication.FormsCookiePath _
            }
            If persistent Then
                cookie.Expires = expiration
            End If

            Return cookie
        End Function


        Public Shared Function RetrieveAuthUser() As Domain.Models.UserSessionModel
            Dim cookieName As String = FormsAuthentication.FormsCookieName
            Dim authCookie As HttpCookie = HttpContext.Current.Request.Cookies(cookieName)
            Dim authTicket As FormsAuthenticationTicket = FormsAuthentication.Decrypt(authCookie.Value)
            Dim userdata As String = authTicket.UserData

            Dim usersessionmodel As New Domain.Models.UserSessionModel
            usersessionmodel = DeserializeUser(userdata)
            Return usersessionmodel
        End Function


        Private Shared Function SerializeUser(ByVal usersessionmodel As Domain.Models.UserSessionModel) As String
            Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
            Dim mem As New IO.MemoryStream
            bf.Serialize(mem, usersessionmodel)
            Return Convert.ToBase64String(mem.ToArray())
        End Function

        Private Shared Function DeserializeUser(ByVal serializedusersessionmodel As String) As Domain.Models.UserSessionModel
            Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
            Dim mem As New IO.MemoryStream(Convert.FromBase64String(serializedusersessionmodel))
            Return DirectCast(bf.Deserialize(mem), Domain.Models.UserSessionModel)
        End Function
    End Class
End Namespace

这里是我创造所有魔法的地方。该方法在继承System.Web.Mvc.Controller的“BaseController”类中

Protected Overrides Function CreateActionInvoker() As System.Web.Mvc.IActionInvoker

            If User.Identity.IsAuthenticated Then ''# this if statement will eventually also check to make sure that the cookie actually exists.

                Dim sessionuser As Domain.Models.UserSessionModel = New Domain.Models.UserSessionModel(OpenIdService.GetOpenId(HttpContext.User.Identity.Name).User)
                HttpContext.Response.Cookies.Add(UrbanNow.Core.Utilities.Authentication.CustomAuthentication.CreateAuthCookie(HttpContext.User.Identity.Name, sessionuser, True))
            End If
End Function

这是我尝试检索信息的方法。

 Dim user As Domain.Models.UserSessionModel = CustomAuthentication.RetrieveAuthUser

【问题讨论】:

  • 我找到了问题的答案。上面的代码可以工作,但是Response.Cookies.Add 没有工作,因为它发生在错误的位置。 cookie 已在身份验证步骤中创建。我必须删除在 Auth 步骤中创建代码的代码,并将其替换为 CreateActionInvoker 方法中的代码。

标签: asp.net vb.net asp.net-membership


【解决方案1】:

首先 ASP.Net Membership 提供者不编写任何 cookie,身份验证 cookie 由 FormsAuthentication 编写。

其次,为什么要干预身份验证 cookie。您可以完全在单独的 cookie 中执行此操作。以下是您可以这样做的方法。

将键值写入 cookie。

//create a cookie
HttpCookie myCookie = new HttpCookie("myCookie");

//Add key-values in the cookie
myCookie.Values.Add("UserId", "your-UserId");
myCookie.Values.Add("UrlSlug", "your-UrlSlug");

//set cookie expiry date-time, if required. Made it to last for next 12 hours.
myCookie.Expires = DateTime.Now.AddHours(12);

//Most important, write the cookie to client.
Response.Cookies.Add(myCookie);

从 cookie 中读取键值。

//Assuming user comes back after several hours. several < 12.
//Read the cookie from Request.
HttpCookie myCookie = Request.Cookies["myCookie"];
if (myCookie == null)
{
    //No cookie found or cookie expired.
    //Handle the situation here, Redirect the user or simply return;
}

//ok - cookie is found.
//Gracefully check if the cookie has the key-value as expected.
if (!string.IsNullOrEmpty(myCookie.Values["UserId"]))
{
    string UserId= myCookie.Values["UserId"].ToString();
    //Yes UserId is found. Mission accomplished.
}

if (!string.IsNullOrEmpty(myCookie.Values["UrlSlug"]))
{
    string UrlSlug = myCookie.Values["UrlSlug"].ToString();
    //Yes key2 is found. Mission accomplished.
}

如果您需要打扰 身份验证 cookie,虽然不是 可取的,这就是你可以做到的。

将键值写入 cookie。

//create a cookie
HttpCookie myCookie = FormsAuthentication.GetAuthCookie("UserName", true);

//Add key-values in the cookie
myCookie.Values.Add("UserId", "your-UserId");
myCookie.Values.Add("UrlSlug", "your-UrlSlug");

//set cookie expiry date-time, if required. Made it to last for next 12 hours.
myCookie.Expires = DateTime.Now.AddHours(12);

//Most important, write the cookie to client.
Response.Cookies.Add(myCookie);

从 cookie 中读取键值。

//Assuming user comes back after several hours. several < 12.
//Read the cookie from Request.
HttpCookie myCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (myCookie == null)
{
    //No cookie found or cookie expired.
    //Handle the situation here, Redirect the user or simply return;
}

//ok - cookie is found.
//Gracefully check if the cookie has the key-value as expected.
if (!string.IsNullOrEmpty(myCookie.Values["UserId"]))
{
    string UserId= myCookie.Values["UserId"].ToString();
    //Yes UserId is found. Mission accomplished.
}

if (!string.IsNullOrEmpty(myCookie.Values["UrlSlug"]))
{
    string UrlSlug = myCookie.Values["UrlSlug"].ToString();
    //Yes key2 is found. Mission accomplished.
}

【讨论】:

  • 抱歉错误。是的,我在我的应用程序中使用了一种表单身份验证。谢谢你的详细建议,我明天去看看(睡觉时间)。
  • 我实际上是在使用 DotNetOpenAuth 作为我的会员资料(找不到 ASP.NET 会员资格)。但我看到 DotNetOpenAuth 正在使用(以某种方式)表单身份验证 cookie...我只是想我可以搭载它。
  • 另外,为什么不建议干扰身份验证cookie?
  • 有没有办法将它添加到 IPrincipal 扩展中,以便我(例如)可以调用 User.Identity.Slug 来获取用户信息?
  • 我认为这是个坏建议。你可以看看我的答案为什么。 @岩石。干杯。
【解决方案2】:

根据具体情况,使用单独的 cookie可能是一个可行的选择,但在我看来,由于几个原因,包括您必须管理多个 cookie 以及管理cookie 的生命周期。

将自定义信息合并到表单工单中的最可靠策略是利用工单的userData 字段。这正是它的用途。

您可以轻松地将自定义数据存储在工单的userData 字段中。

关于要存储在票证中的数据大小有一些问题需要注意,这些问题已在here 中进行了解释

here 是一个小类,可以帮助您在表单票证中存储自定义数据。

【讨论】:

  • 因此,如果我有一个包含自定义数据的小类对象,我需要对 ID, RegionID, Username, Slug 进行持久访问,我是用逗号分隔的字符串将它发送到 userData 对象还是需要一些怎么searialzie把它放进去?
  • @rock,如果它像您呈现的对象一样简单,那么使用 csv 应该没问题。无需过度设计。但是您需要注意对最终的“用户数据”值进行 urlencoding,因为嵌入的逗号和分号会破坏 cookie。当然,这意味着您需要对其进行 urldecode 以补充水分,同时注意嵌入的逗号。您的预期数据将决定您需要保持什么样的意识水平。祝你好运。
  • 我已经用一些序列化逻辑测试了你的代码,反序列化位被破坏了。我已经编辑了原始问题以进行澄清......你能看到我可能遗漏了什么吗?
  • @rock - 您是否在创建工单后或从新请求中读取工单时丢失了 userData?如果您在创建票证后没有立即获得 userData,则代码的 VB 转换存在问题,如果您在下一个请求中丢失了数据,则说明您设置 cookie 的方式存在问题。您是在设置票证还是其他代码正在覆盖它?
  • 我进行了另一次编辑。基本上,我在继承自 System.Web.Mvc.Controller 的 BaseController 的 CreateActionInvoker 方法中启动您的代码。然后我在我的控制器RetrieveAuthUserActionResult
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-07
  • 2011-08-26
相关资源
最近更新 更多