Asp.net web api 存储数据库查询中登录的用户ID,以便将来在控制器中使用
我的razor页面应用程序允许用户登录,一旦他们登录,我就使用身份验证来确认用户名和密码是否正确,然后将其加载到单页面vue应用程序。我的vue应用程序使用我制作的控制器检索和发送数据,该控制器利用dapper查询和更新数据库。为了使控制器更安全,并且仅限于该用户,所有查询都在个人ID上执行where子句。因此,我需要找到一种方法来创建这个全局变量,然后从下面的登录代码中为该变量分配ID,然后控制器和我以后可能创建的任何其他razor页面都可以访问该变量。如大多数答案所示,在不使用会话的情况下,这是否可行?我的身份验证代码如下:Asp.net web api 存储数据库查询中登录的用户ID,以便将来在控制器中使用,asp.net-web-api,asp.net-core-mvc,asp.net-core-3.1,asp.net-core-5.0,Asp.net Web Api,Asp.net Core Mvc,Asp.net Core 3.1,Asp.net Core 5.0,我的razor页面应用程序允许用户登录,一旦他们登录,我就使用身份验证来确认用户名和密码是否正确,然后将其加载到单页面vue应用程序。我的vue应用程序使用我制作的控制器检索和发送数据,该控制器利用dapper查询和更新数据库。为了使控制器更安全,并且仅限于该用户,所有查询都在个人ID上执行where子句。因此,我需要找到一种方法来创建这个全局变量,然后从下面的登录代码中为该变量分配ID,然后控制器和我以后可能创建的任何其他razor页面都可以访问该变量。如大多数答案所示,在不使用会话的情况下,
using System;
using System.Linq;
using System.Threading.Tasks;
using ARMS_2._0_LOCAL.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Security.Claims;
namespace ARMS_2._0_LOCAL.Pages.Login
{
public class IndexModel : PageModel
{
private readonly LoginDBContext _context;
public IndexModel(LoginDBContext context)
{
_context = context;
}
public void OnGet()
{
}
[BindProperty]
[Required(ErrorMessage ="Username field is required.")]
public string UserName { get; set; }
[BindProperty, DataType(DataType.Password)]
[Required(ErrorMessage ="Password field is required.")]
public string Password { get; set; }
[BindProperty]
public bool RememberMe { get; set; }
public string Message { get; set; }
public async Task<IActionResult> OnPost()
{
if (ModelState.IsValid)
{
//var UserResults = _context.UserAccounts.FromSqlInterpolated($"SELECT USERACCOUNT.USERNAME, USERACCOUNT.PASSWORD, USERACCOUNT.ID,USERACCOUNT.ACCESS_LEVEL FROM DBO.USERACCOUNT WHERE USERACCOUNT.USERNAME={UserName}");
var users = _context.UserAccounts
.Where(a => a.Username == UserName)
.Select(a => new { a.Id, a.Username, a.Password})
.ToArray();
if (users.Length == 1) //if we have more than 1 result we have security issue so do not allow login
{
var passwordHasher = new PasswordHasher<string>();
//To has the password use this var hashedPassword = passwordHasher.HashPassword(UserName, Password);
var user = users.First();
if (passwordHasher.VerifyHashedPassword(user.Username, user.Password, Password) == PasswordVerificationResult.Success)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, UserName)
};
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
if (RememberMe)
{
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
new AuthenticationProperties
{
IsPersistent = RememberMe,
ExpiresUtc = DateTimeOffset.UtcNow.AddHours(2)
});
}
else
{
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity));
}
GlobalReusableIDVariable= user.ID;
return RedirectToPage("/index");
}
else
{
// Setting.
ModelState.AddModelError("Message", "The password is incorrect.");
return Page();
}
}
else
{
// Setting.
ModelState.AddModelError("Message", "The username is incorrect.");
return Page();
}
}
else
{
return Page();
}
}
}
}
为了使控制器更加安全和受限于该用户,所有查询都在个人ID上做WHERE子句。您可以考虑将[授权]属性应用到控制器,然后,只有登录的用户才能访问控制器中的动作方法。参考:我可以这样做,但我还需要保护控制器,作为第二道防线,用于相互登录的用户。使用服务器端变量将允许我从控制器请求中删除该参数并全局使用。这有意义吗?