问题
I have a system that I use Asp.Net Identity to log users that have claims. Each user have different access to the System functionalities because I've created different Authorization filters.
My issue is this one: the system is for the management of car body work and painting. It has companies and the users log with the Asp.Net Identity technology. But I need to log special users that has no user name or password, these useras are the clients of the companies, that must log with License Plate of the cliente vehicle and some personal info like the Social Security Number.
What I've manageged to do until now: find if the client has a vehicle in one company and verify if the client data provided is correct. But the System fail in the SignInManager.SignInAsync() methrod. It gives me the error that the UserId was not found.
Here is my code:
if (!ModelState.IsValid)
{
return View(model);
}
var serviceOrder = Repository.ServiceOrders
.Where(so => so.IsActive && so.Vehicle.LicensePlate == model.LicensePlate &&
so.Client.Document.Substring(0, 3) == model.Password)
.OrderByDescending(so => so.CreatedAt).FirstOrDefault();
if (serviceOrder != null)
{
var userId = Guid.NewGuid().ToString();
var user = new ServerModels.User
{
Id = userId,
Name = serviceOrder.Client.Name,
UserName = model.LicensePlate,
SecurityStamp = userId,
Claims =
{
new IdentityUserClaim
{
UserId = userId,
ClaimType = ClaimTypes.Role,
ClaimValue = AppRoleClaims.Client
},
new IdentityUserClaim
{
UserId = userId,
ClaimType = AppAccessClaims.ClientScreenAccess,
ClaimValue = AppAccessClaimsValues.Visualize,
}
}
};
try
{
await SignInManager.SignInAsync(user, model.RememberMe, false);
return Redirect("/cliente/consultarveiculo");
}
catch (Exception ex)
{
ModelState.AddModelError("", "Tentativa de login inválida. - " + ex.Message);
return View(model);
}
And the error StackTrace:
em Microsoft.AspNet.Identity.UserManager`2.<GetSecurityStampAsync>d__42.MoveNext()
--- Fim do rastreamento de pilha do local anterior onde a exceção foi gerada ---
em System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
em System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
em System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
em Microsoft.AspNet.Identity.TaskExtensions.CultureAwaiter`1.GetResult()
em Microsoft.AspNet.Identity.ClaimsIdentityFactory`2.<CreateAsync>d__0.MoveNext()
--- Fim do rastreamento de pilha do local anterior onde a exceção foi gerada ---
em System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
em System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
em System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
em SGOM.Server.Models.User.<GenerateUserIdentityAsync>d__20.MoveNext() na C:\Users\Adalto\Documents\Visual Studio 2015\Projects\MonitoraCar\SGOM\Server\Models\Models\User.cs:linha 25
--- Fim do rastreamento de pilha do local anterior onde a exceção foi gerada ---
em System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
em System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
em System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
em Microsoft.AspNet.Identity.TaskExtensions.CultureAwaiter`1.GetResult()
em Microsoft.AspNet.Identity.Owin.SignInManager`2.<SignInAsync>d__2.MoveNext()
--- Fim do rastreamento de pilha do local anterior onde a exceção foi gerada ---
em System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
em System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
em System.Runtime.CompilerServices.TaskAwaiter.GetResult()
em SGOM.Client.Web.WebApp.Controllers.AccountController.<ClientLogin>d__13.MoveNext() na C:\Users\Adalto\Documents\Visual Studio 2015\Projects\MonitoraCar\SGOM\Client\Web\WebApp\Controllers\AccountController.cs:linha 195
Client login screen
回答1:
Following the link that Sam Farajpour Guamari passed I came up to this solution:
public ActionResult ClientLogin(ClientLoginViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var serviceOrder = Repository.ServiceOrders
.Where(so => so.IsActive && so.Vehicle.LicensePlate == model.LicensePlate &&
so.Client.Document.Replace(".", "").Replace("-", "").Replace("/", "").Substring(0, 6) == model.Password)
.OrderByDescending(so => so.CreatedAt).FirstOrDefault();
if (serviceOrder != null)
{
try
{
var identity = new ClaimsIdentity(
new[]
{
// adding following 2 claims just for supporting default antiforgery provider
new Claim(ClaimTypes.NameIdentifier, "AnonymousUserID"),
new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string"),
new Claim(ClaimTypes.Name, serviceOrder.Client.Name),
new Claim(ClaimTypes.Role, AppRoleClaims.Client),
new Claim(AppAccessClaims.ClientScreenAccess, AppAccessClaimsValues.Visualize)
},
DefaultAuthenticationTypes.ApplicationCookie);
HttpContext.GetOwinContext().Authentication.SignIn(
new AuthenticationProperties { IsPersistent = model.RememberMe }, identity);
return Redirect("/cliente/consultarveiculo");
}
catch (Exception ex)
{
ModelState.AddModelError("", "Tentativa de login inválida. - " + ex.Message);
return View(model);
}
}
ModelState.AddModelError("", "Tentativa de login inválida. - Nenhum cliente com a placa e a senha informada.");
return View(model);
}
That worked very well: create claims on the fly and use them to authenticate.
Link to the original post:
MVC 5 Identity (v2) Authentication Without Creating an Application User
来源:https://stackoverflow.com/questions/41851239/how-can-i-log-a-client-in-asp-net-mvc-with-no-user