C# ASP.NET MVC 5上的ASP.NET标识设置的Controller.User不一致
我试图将身份验证与控制器分离,因此我制作了一个C# ASP.NET MVC 5上的ASP.NET标识设置的Controller.User不一致,c#,asp.net-mvc,asp.net-mvc-5,asp.net-identity,owin,C#,Asp.net Mvc,Asp.net Mvc 5,Asp.net Identity,Owin,我试图将身份验证与控制器分离,因此我制作了一个AuthenticationService,并使用Ninject将其注入身份验证控制器(DefaultController)。下面是AuthenticationService的实现: public sealed class AuthenticationService { private IAuthenticationManager AuthenticationManager { get; set; } private UserMana
AuthenticationService
,并使用Ninject将其注入身份验证控制器(DefaultController
)。下面是AuthenticationService
的实现:
public sealed class AuthenticationService {
private IAuthenticationManager AuthenticationManager { get; set; }
private UserManager<Employee, int> EmployeeManager { get; set; }
public AuthenticationService(
IAuthenticationManager authenticationManager,
UserManager<Employee, int> employeeManager) {
this.AuthenticationManager = authenticationManager;
this.EmployeeManager = employeeManager;
}
public bool SignIn(
CredentialsInput credentials) {
Employee employee = this.EmployeeManager.Find(credentials.Email, credentials.Password);
if (employee != null) {
ClaimsIdentity identityClaim = this.EmployeeManager.CreateIdentity(employee, DefaultAuthenticationTypes.ApplicationCookie);
if (identityClaim != null) {
this.AuthenticationManager.SignIn(new AuthenticationProperties(), identityClaim);
return true;
}
}
return false;
}
public void SignOut() {
this.AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
}
}
哦,为了更好地衡量,这里是DefaultController
:
public sealed class DefaultController : Controller {
private AuthenticationService AuthenticationService { get; set; }
public DefaultController(
AuthenticationService authenticationService) {
this.AuthenticationService = authenticationService;
}
[HttpPost, AllowAnonymous, ValidateAntiForgeryToken]
public RedirectToRouteResult Default(
[Bind(Prefix = "Credentials", Include = "Email,Password")] CredentialsInput credentials) {
if (base.ModelState.IsValid
&& this.AuthenticationService.SignIn(credentials)) {
// Place of error. The IsInRole() method doesn't return
// the correct answer because the
// IUserStore<>.FindByIdAsync() method is not setting
// the correct data.
if (this.User.IsInRole("Technician")) {
return this.RedirectToAction<TechniciansController>(
c =>
c.Default());
}
return this.RedirectToAction(
c =>
c.Dashboard());
}
return this.RedirectToAction(
c =>
c.Default());
}
[HttpGet]
public RedirectToRouteResult SignOut() {
this.AuthenticationService.SignOut();
return this.RedirectToAction(
c =>
c.Default());
}
}
嗯,我没有一个真正的解决办法,但我有一个有效的办法。由于在登录过程中未设置用户
,因此我重定向到另一个名为DefaultRedirect
的操作,在该操作中,我现在可以完全访问用户
属性,并可以从那里重定向我真正想要的方式。这是一个肮脏的骗局,使事情顺利进行,但这不是一个真正的解决办法。我仍然认为ASP.NET标识在某种程度上无法正常工作。不管怎么说,这是我的骗局:
[HttpPost, AllowAnonymous, ValidateAntiForgeryToken]
public RedirectToRouteResult Default(
[Bind(Prefix = "Credentials", Include = "Email,Password")] CredentialsInput credentials) {
if (base.ModelState.IsValid
&& this.AuthenticationService.SignIn(credentials)) {
return this.RedirectToAction(
c =>
c.DefaultRedirect());
}
return this.RedirectToAction(
c =>
c.Default());
}
[HttpGet]
public RedirectToRouteResult DefaultRedirect() {
if (this.User.IsInRole("Technician")) {
return this.RedirectToAction<TechniciansController>(
c =>
c.Default());
}
return this.RedirectToAction(
c =>
c.Dashboard());
}
[HttpPost,AllowAnonymous,ValidateAntiForgeryToken]
公共重定向路由结果默认值(
[Bind(Prefix=“Credentials”,Include=“Email,Password”)]Credentials输入凭据){
如果(base.ModelState.IsValid
&&此.AuthenticationService.SignIn(凭据)){
返回此.RedirectToAction(
c=>
c、 DefaultRedirect());
}
返回此.RedirectToAction(
c=>
c、 默认值());
}
[HttpGet]
公共重定向器路由结果DefaultRedirect(){
if(this.User.IsInRole(“技术人员”)){
返回此.RedirectToAction(
c=>
c、 默认值());
}
返回此.RedirectToAction(
c=>
c、 仪表板());
}
如果有人知道,我仍在寻找真正的解决方案为了清楚起见--ASP.NET标识与在MVC中设置用户属性无关。这就是Katana身份验证中间件的工作。ASP.NET标识在数据库中管理用户的凭据和标识数据。我建议不要使用任务中的异步方法。任务中的异步方法使用IIS线程池中的线程,这意味着服务HTTP请求的线程更少。此外,由于方法
IsInRoleAsync()
的细节用于授权,因此调用线程无论如何都应该在继续(授权/拒绝)之前等待结果,这意味着使方法异步实际上会使进程变慢。完全同意@ErikPhilips。您不应该使用其他线程进行身份验证。他打电话给我的时候正在打it@ErikPhilips,我同意你的看法,但是所有的接口方法都是异步的,所以我没有选择的余地。我创建了我的实现,方法是用ILSpy在EF标识实现中进行搜索,并与它们所做的大部分匹配。我唯一不同的做法是使用我已经存在的存储库。也就是说,我在我的登录和注销方法中使用了同步扩展方法,它们只是异步方法的包装,我认为异步方法应该强制它们是同步的?对于那些感兴趣的人,我在回答这个问题时描述了我对ASP.NET Identity的实现:。
public sealed class DefaultController : Controller {
private AuthenticationService AuthenticationService { get; set; }
public DefaultController(
AuthenticationService authenticationService) {
this.AuthenticationService = authenticationService;
}
[HttpPost, AllowAnonymous, ValidateAntiForgeryToken]
public RedirectToRouteResult Default(
[Bind(Prefix = "Credentials", Include = "Email,Password")] CredentialsInput credentials) {
if (base.ModelState.IsValid
&& this.AuthenticationService.SignIn(credentials)) {
// Place of error. The IsInRole() method doesn't return
// the correct answer because the
// IUserStore<>.FindByIdAsync() method is not setting
// the correct data.
if (this.User.IsInRole("Technician")) {
return this.RedirectToAction<TechniciansController>(
c =>
c.Default());
}
return this.RedirectToAction(
c =>
c.Dashboard());
}
return this.RedirectToAction(
c =>
c.Default());
}
[HttpGet]
public RedirectToRouteResult SignOut() {
this.AuthenticationService.SignOut();
return this.RedirectToAction(
c =>
c.Default());
}
}
public Task<Employee> FindByIdAsync(
int employeeId) {
this.ThrowIfDisposed();
return this.Repository.FindSingleOrDefaultAsync<Employee, int>(employeeId);
}
public Task<bool> IsInRoleAsync(
Employee employee,
string roleName) {
this.ThrowIfDisposed();
if (employee == null) {
throw new ArgumentNullException("employee");
}
if (String.IsNullOrEmpty(roleName)) {
throw new ArgumentNullException("roleName");
}
return Task.FromResult<bool>(employee.Roles.Any(
r =>
(r.Name == roleName)));
}
[HttpPost, AllowAnonymous, ValidateAntiForgeryToken]
public RedirectToRouteResult Default(
[Bind(Prefix = "Credentials", Include = "Email,Password")] CredentialsInput credentials) {
if (base.ModelState.IsValid
&& this.AuthenticationService.SignIn(credentials)) {
return this.RedirectToAction(
c =>
c.DefaultRedirect());
}
return this.RedirectToAction(
c =>
c.Default());
}
[HttpGet]
public RedirectToRouteResult DefaultRedirect() {
if (this.User.IsInRole("Technician")) {
return this.RedirectToAction<TechniciansController>(
c =>
c.Default());
}
return this.RedirectToAction(
c =>
c.Dashboard());
}