我有一个名为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);
}我的网址是"/Home/Profile?agencyID=5809&contactID=19492“。
但是,我现在可以更改URL中的contactID,现在我在另一个用户的配置文件上,而无需经过授权。
我怎么才能避免这种情况?显然,我不能将密码作为参数包含在配置文件方法中,因为它在URL中是可见的。我应该采取什么方法?
更新-解决
感谢大家的评论。卡米洛·特列文托的回答解决了我的问题。
我将所需的信息添加到UserSignIn方法中的声明中,并删除了Profile方法中的参数,在该方法中,我可以从活动用户检索所需的信息。现在,我可以确保只有授权用户才能到达“配置文件”控制器方法。
我唯一需要改变的就是直接的演员阵容。我的编译器不喜欢它,所以我只是将它改为使用解析:
int agency_id = int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value);
int contact_id = int.Parse(User.FindFirst(ClaimTypes.Sid).Value);发布于 2018-11-08 13:08:29
您可以在声明中添加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);
}https://stackoverflow.com/questions/53207893
复制相似问题