如何防止用户访问其他用户的个人资料?

时间:2018-11-08 12:37:28

标签: c# asp.net-core

我有一个称为 UserSignIn 的控制器方法,用于验证用户身份。 “候选人”参数是一个模型,其中包含包括联系人的电子邮件地址和密码在内的字段。

该模型还包含字段“ AgencyID”和“ ContactID”。使用这些是为了让我知道要连接到哪个数据库(AgencyID)和要获取哪个联系人记录(ContactID)。登录的用户是代理商的联系人。

[HttpPost()]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> UserSignIn(Candidate can)
{
    bool is_err = false;
    string err = string.Empty;
    Candidate c_signed_in = new Candidate();

    // check data
    if (string.IsNullOrEmpty(can.Email))
    {
        is_err = true;
        err += "<li>Missing email address.</li>";
    }
    if (string.IsNullOrEmpty(can.AccountPassword))
    {
        is_err = true;
        err += "<li>Missing password.</li>";
    }

    // get candidate
    if (ModelState.IsValid && !is_err)
    {
        c_signed_in = await Repository.GetCandidate(can.AgencyID, 0, can.Email.ToLower(), can.AccountPassword, hostingEnv.WebRootPath);
        if (c_signed_in.ContactID == 0)
        {
            is_err = true;
            err += "<li>No account found. Check your credentials.</li>";
        }
    }

    // check model state
    if (!ModelState.IsValid || is_err)
    {
        Candidate c_current = await Repository.GetBlankCandidate(can, false);
        c_current.IsModeSignIn = true;
        if (is_err)
            c_current.ErrsSignIn = "<ul class=\"text-danger\">" + err + "</ul>";
        return View("Agency", c_current);
    }

    // create claims
    var claims = new List<Claim>
    {
        //new Claim(ClaimTypes.Name, c_signed_in.FirstName + gFunc.SPACE + c_signed_in.FamilyName),
        new Claim(ClaimTypes.Sid, c_signed_in.ContactID.ToString()),
        new Claim(ClaimTypes.Email, c_signed_in.Email)
    };

    // create identity
    var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); // cookie or local

    // create principal
    ClaimsPrincipal principal = new ClaimsPrincipal(new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme));

    // sign-in
    await HttpContext.SignInAsync(scheme: CookieAuthenticationDefaults.AuthenticationScheme, principal: principal);

    // add to log
    gFunc.AddLogEntry("SignIn Candidate: " + c_signed_in.FirstName + gFunc.SPACE + c_signed_in.FamilyName + " - " + c_signed_in.Email);

    // fini
    return RedirectToAction("Profile", new { agencyID = c_signed_in.AgencyID, contactID = c_signed_in.ContactID });
}

成功后,此方法将重定向到一个名为“个人资料”的方法,该方法显示用户的个人资料。

[HttpGet]
[Authorize]
public async Task<ActionResult> Profile(int agencyID, int contactID)
{
    Candidate can = await Repository.GetCandidate(agencyID, contactID, string.Empty, string.Empty, hostingEnv.WebRootPath);
    if (can.ContactID == 0)
    {
        int id = agencyID;
        return RedirectToAction("Agency", new { agencyID = id });
    }
    return View("Profile", can);
}

我的URL现在为“ / Home / Profile?agencyID = 5809&contactID = 19492

但是,我现在只需更改URL中的contactID,现在我就在未经授权的情况下位于另一个用户的个人资料中。

如何避免这种情况?显然,我不能在 Profile 方法中将密码作为参数包含进来,因为它只是在URL中可见。我应该采取什么方法?

更新-已解决

感谢大家的评论。 Camilo Terevinto的答案解决了我的问题。

我在 UserSignIn 方法中的声明中添加了所需的信息,并在 Profile 方法中删除了参数,以便从活动目录中检索所需的信息用户。现在,我可以确保只有授权用户才能使用“配置文件”控制器方法。

我唯一需要更改的是直接int cast。我的编译器不喜欢它,所以我只是将其更改为使用解析:

    int agency_id = int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value);
    int contact_id = int.Parse(User.FindFirst(ClaimTypes.Sid).Value);

1 个答案:

答案 0 :(得分:4)

您可以在声明中添加 agencyID contactID

new Claim(ClaimTypes.Sid, c_signed_in.ContactID.ToString()),
new Claim(ClaimTypes.Email, c_signed_in.Email),
new Claim(ClaimTypes.NameIdentifier,c_signed_in.agencyID.ToString())

在控制器中,您可以从记录的用户数据中获取它:

[HttpGet]
[Authorize]
public async Task<ActionResult> Profile()
{
    int agencyID = (int)User.FindFirst(ClaimTypes.NameIdentifier).Value
    int contactID = (int) User.FindFirst(ClaimTypes.Sid).Value

    Candidate can = await Repository.GetCandidate(agencyID, contactID, string.Empty, string.Empty, hostingEnv.WebRootPath);
    if (can.ContactID == 0)
    {
        int id = agencyID;
        return RedirectToAction("Agency", new { agencyID = id });
    }

    return View("Profile", can);
}