Как предотвратить доступ пользователя к профилю другого пользователя? - PullRequest
0 голосов
/ 08 ноября 2018

У меня есть метод контроллера с именем 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 сейчас "/ Главная / Профиль? AgencyID = 5809 & contactID = 19492

Однако теперь я могу просто изменить contactID в URL, и теперь я нахожусь в профиле другого пользователя без авторизации.

Как мне избежать этого? Очевидно, что я не могу включить пароль в качестве параметра в метод Profile , потому что он просто будет виден в URL. Какой подход я должен выбрать?

ОБНОВЛЕНИЕ - РЕШЕНО

Спасибо всем за ваши комментарии. Ответ Камило Теревинто решил мою проблему.

Я добавил необходимую информацию к утверждениям в методе UserSignIn и удалил параметры в методе Profile , где я могу получить необходимую информацию от активного пользователя. Теперь я могу гарантировать, что только авторизованный пользователь сможет получить доступ к методу контроллера «Профиль».

Единственное, что я должен был изменить, - это прямой международный отряд. Моему компилятору это не понравилось, поэтому я просто изменил его на использование синтаксического разбора:

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

1 Ответ

0 голосов
/ 08 ноября 2018

Вы можете добавить 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...