使用FormsAuthentication.SetAuthCookie存储更多信息

46

我正在使用aspx和c#来设置登录认证cookie。

FormsAuthentication.SetAuthCookie(UserName, True)

我希望在同一个cookie中存储更多的信息。我可以向该身份验证cookie添加值,还是必须使用第二个http cookie?

基本上,我想要存储用户的Id,以便我可以使用用户表行键访问数据库。

谢谢, Eden

5个回答

51
您可以向FormsAuthenticationTicket添加用户数据,然后自己生成cookie。 在MSDN FormsAuthenticationTicket文档中有一个示例。 编辑
请注意,在创建票证时,您需要设置超时时间,通常应与web.config中配置的值相同。不幸的是,在Framework 3.5或更早版本中,FormsAuthentication类没有公开此超时时间。对于解决方法,请使用此连接反馈项中描述的技术之一。
更新
那个Connect反馈项已经不存在了,很遗憾。希望您能简要描述一下这些技术是什么。
是的,微软放弃了历史上的Connect项目,这真是太可惜了。如果我没记错,他们建议的两种技术是:
1.使用WebConfigurationManager读取相关配置部分并获取超时值。
2.使用FormsAuthentication.GetAuthCookie创建cookie,使用FormsAuthentication.Decrypt进行解密并检查生成的FormsAuthenticationTicket。
或者升级到.NET 4.x,其中有一个FormsAuthentication.Timeout属性。

查看 这个问题 以获取更多信息


谢谢!这正是我一直在寻找的!它似乎与FormsAuthentication.SetAuthCookie在asp.net 3.5中的行为重叠(我没有时间使用反编译器),只有一个小差异,就是您可以将任意数据附加到cookie(不仅仅是名称)。再次感谢! - Eden
那个“Connect”反馈项目不见了,遗憾。希望您能简要描述一下这些技术是什么... - Roman Starkov
1
在.NET 4.x中,创建新票证时使用FormsAuthentication.Timeout的方式如下:DateTime.Now.Add(FormsAuthentication.Timeout)。 - Lucio Paiva

16

只要对你有用,你可以在auth cookie中放入任何内容。但是,如果你要存放敏感信息,至少应该加密,但我建议不要将敏感信息放在那里。你可以这样做:

Forms.SetAuthCookie (UserName + "|" + UserId, true);
然后,每当您需要用户名或用户ID时,它就在那里。只需加载Cookie并解析出所需的值即可。
再次强烈建议不要这样做,特别是按照我上面所述的方式。尽管如此,这是有可能的。您应该创建访问器方法来获取数据:
public int CurrentUserId
{
    get
    {
        int userId = 0;

        if (HttpContext.Current.Request.IsAuthenticated)
        {
            userId = Convert.ToInt32(HttpContext.Current.User.Identity.Name.Split('|')[1]);
        }

        return userId;
    }
}

public string CurrentUserName
{
    get
    {
        string userName = string.Empty;

        if (HttpContext.Current.Request.IsAuthenticated)
        {
            userName = HttpContext.Current.User.Identity.Name.Split('|')[0];
        }

        return userName;
    }
}

我应该指出,我在这里介绍的方法是“权宜之计”,可以工作,但如果我想对整个系统产生更小的影响,我会使用Joe提出的方法。 - andymeadows

3

使用 "|" 来添加更多信息是明智的做法。如果微软有另一个重载方法

public static void SetAuthCookie(String userName, bool createPersistentCookie, string userData)`

然后我们的生活会更加轻松,我们的代码会更加安全。

1

将用户ID作为userName参数传递。

FormsAuthentication.SetAuthCookie(userId, True)

你是如何保护你的身份验证票据的?

5
我不想使用名称来传递它,而是想向同一身份验证cookie中添加更多数据。这是否有可能? - Eden
1
@Eden,你解决了你的问题吗?我正在使用相同的方法,但不知道如何将userId和roles最好地存储在同一个ticket中? - c-sharp-and-swiftui-devni

0

您可以将额外的信息存储在FormsAuthenticationTicketUserData属性中:

using Newtonsoft.Json;
using System.Web;
using System.Web.Security;

public class LoggedInUser
{
    public string FirstName { get; set; } = null;
    public bool IsAdmin { get; set; } = false;
}

public static class Authentication
{
    static void SignIn(
        HttpContextBase context,
        string emailAddress,
        bool rememberMe,
        LoggedInUser user = null)
    {
        var cookie = FormsAuthentication.GetAuthCookie(
            emailAddress.ToLower(),
            rememberMe);
        var oldTicket = FormsAuthentication.Decrypt(cookie.Value);
        var newTicket = new FormsAuthenticationTicket(
            oldTicket.Version,
            oldTicket.Name,
            oldTicket.IssueDate,
            oldTicket.Expiration,
            oldTicket.IsPersistent,
            JsonConvert.SerializeObject(user ?? new LoggedInUser()));

        cookie.Value = FormsAuthentication.Encrypt(newTicket);

        context.Response.Cookies.Add(cookie);
    }

    static void SignOut(HttpContextBase context)
    {
        FormsAuthentication.SignOut();
    }

    static LoggedInUser GetLoggedInUser()
    {
        if (HttpContext.Current.User?.Identity?.Name != null && HttpContext.Current.User?.Identity is FormsIdentity identity)
            return JsonConvert.DeserializeObject<LoggedInUser>(identity.Ticket.UserData);

        return new LoggedInUser();
    }
}

进一步阅读:https://learn.microsoft.com/zh-cn/aspnet/web-forms/overview/older-versions-security/introduction/forms-authentication-configuration-and-advanced-topics-cs#step-4-storing-additional-user-data-in-the-ticket

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接