2

[这个问题与 ASP.NET MVC4 有关,它是关于最佳实践方法 - 所以请不要建议黑客。]

我想使用请求 URL 中发送的身份验证令牌对用户进行身份验证。它的工作原理类似于密码重置令牌,但在这种情况下,它不会进入重置页面,而是授予对网站某些部分的访问权限。这个想法是将带有身份验证令牌的 URL 发送到经过验证的用户电子邮件地址。用户无需输入密码即可单击该链接并执行某些操作。

开箱即用的 ASP.NET 具有 [Authorize] 属性和 SimpleMembershipProvider - 这些似乎工作得很好,但它们在幕后做了一些巫术魔法(比如自动生成数据库表),所以我不知道如何扩展它们以添加此基于链接的身份验证令牌。

我不期待一个确切的答案,但请指出我正确的方向。

谢谢!

4

3 回答 3

3

呃,广泛的问题。但我至少会尝试将您引向正确的方向。

因此,首先如果建议您使用表单身份验证作为基础,但您必须自定义使用它。而且我认为您不想使用 cookie 进行身份验证,因为这是表单身份验证的本机行为。

您应该考虑的最重要的一点是让您自定义基于查询字符串令牌的身份验证。

  1. 创建一个登录操作,在此操作中您将授权用户,如果他已授予访问权限,您要求 FormsAuthentication 创建 AuthCookie。接下来,您只需将 httpCookie.Value 作为您将在查询字符串中携带的身份验证令牌。

  2. 您需要实现将处理此查询字符串标记并将其转换为 cookieApplication_BeginRequest的in 。通过这种方法,您可以利用所有 ASP.NET 表单身份验证基础结构。Global.asax

这是没有代码的相当高级的图片。如果您需要更详细的帮助,我也可以提供给您。

于 2013-03-07T08:07:19.497 回答
1

Action您应该只使用接受的常规HttpGet。收到token后立即作废,不能再次使用。此外,只接受在您预定义的时间段范围内的令牌,例如 24 或 72 小时。

于 2013-03-07T08:01:06.453 回答
0

谢谢彼得的想法。

如果 smb 需要为旧的 ASP.NET MVC5 创建 JWT 令牌授权。我写了一个小例子。我不会将 cookie 序列化为 JWT。我创建了一个 JWT,然后在 BeginRequest 中检查它。如果一切正常,我创建一个 cookie 并将其设置为 httpContext.Request。我为应用程序使用了身份验证模式 =“表单”,它需要 cookie。

创建 JWT 令牌:

const string secret = "GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk";
[AllowAnonymous]
[HttpPost]
public ActionResult LoginJWT(LoginViewModel model)
{
    ActionResult response = null;
    if (ModelState.IsValid)
    {
        if (true) //todo: check user login&password
        {
            var payload = new Dictionary<string, object>
            {
                { "iss", "subject" },
                { "sub", "api" },
                { "exp", DateTimeOffset.UtcNow.AddHours(2).ToUnixTimeSeconds()},
                { "iat",  DateTimeOffset.UtcNow.ToUnixTimeSeconds()},
                { "jti", Guid.NewGuid() },
                { "uid", "64" } //custom field for identificate user
            };

            IJwtAlgorithm algorithm = new HMACSHA256Algorithm(); // symmetric
            IJsonSerializer serializer = new JsonNetSerializer();
            IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
            IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);

            var token = encoder.Encode(payload, secret);
            response = Content(token);
        }
        else
        {
            response = new HttpStatusCodeResult(System.Net.HttpStatusCode.BadRequest, "Login or password are not found");
        }
    }
    else
    {
        response = new HttpStatusCodeResult(System.Net.HttpStatusCode.BadRequest, "Errors in Model");
    }
    return response;
}

检查 Global.asax 中的 JWT 令牌:

public override void Init()
        {
            this.BeginRequest += this.BeginRequestHandler;
            base.Init();
        }

private void BeginRequestHandler(object sender, EventArgs e)
        {
            var bearerToken = this.Context.Request.Headers["Authorization"];
            if (bearerToken != null)
            {
                var token = bearerToken.StartsWith("Bearer ") ? bearerToken.Substring(7) : bearerToken;
                const string secret = "GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk";
                int userId = 0;
                try
                {
                    IJsonSerializer serializer = new JsonNetSerializer();
                    var provider = new UtcDateTimeProvider();
                    IJwtValidator validator = new JwtValidator(serializer, provider);
                    IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                    IJwtAlgorithm algorithm = new HMACSHA256Algorithm(); // symmetric
                    IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm);

                    var json = decoder.DecodeToObject<IDictionary<string, string>>(token, secret, verify: true);

                    if (json.TryGetValue("uid", out var uid))
                    {
                        userId = Convert.ToInt32(uid);
                    }
                }
                catch (TokenExpiredException)
                {
                    Console.WriteLine("Token has expired");
                }
                catch (SignatureVerificationException)
                {
                    Console.WriteLine("Token has invalid signature");
                }
                if (userId != 0)
                {
                    // check user by id, if found create cookie.
                }
            }
        }

我用过: jwt-dotnet/jwt library 7.2.1

于 2020-09-03T02:25:10.277 回答