身份验证 – 如何使用ASP.NET身份在Web API 2中实现双因素身份验
我已经看到了关于如何在web api中创建双因素身份验证的链接
Two Factor Auth using goolgle authenticator,但我的要求却略有不同.
>我想使用双因素身份验证来发出访问令牌. (如果用户已选择启用双因素身份验证) 我当前实现的问题是,当我调用SignInManager.SendTwoFactorCodeAsync(“电话代码”)时,我得到错误用户ID未找到. 为了调试,我尝试调用User.Identity.GetUserId();并返回正确的用户ID. 我检查了Microsoft.AspNet.Identity.Owin程序集的源代码 public virtual async Task<bool> SendTwoFactorCodeAsync(string provider) { var userId = await GetVerifiedUserIdAsync().WithCurrentCulture(); if (userId == null) { return false; } var token = await UserManager.GenerateTwoFactorTokenAsync(userId,provider).WithCurrentCulture(); // See IdentityConfig.cs to plug in Email/SMS services to actually send the code await UserManager.NotifyTwoFactorTokenAsync(userId,provider,token).WithCurrentCulture(); return true; } public async Task<TKey> GetVerifiedUserIdAsync() { var result = await AuthenticationManager.AuthenticateAsync(DefaultAuthenticationTypes.TwoFactorCookie).WithCurrentCulture(); if (result != null && result.Identity != null && !String.IsNullOrEmpty(result.Identity.GetUserId())) { return ConvertIdFromString(result.Identity.GetUserId()); } return default(TKey); } 从上面的代码可以看出,SendTwoFactorCodeAsync方法在内部调用GetVerifiedUserIdAsync,它检查双因素身份验证cookie.由于这是一个web api项目,因此不存在cookie并返回0,导致找不到用户id错误. 我的问题,如何使用asp.net身份在web api中正确实现双因素身份验证? 解决方法
这就是我实现的,以便在api上工作.我假设您使用的是默认的ASP.NET单用户模板.
1.ApplicationOAuthProvider 在GrantResourceOwnerCredentials方法中,您必须添加此代码 var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>(); ApplicationUser user = await userManager.FindAsync(context.UserName,context.Password); var twoFactorEnabled = await userManager.GetTwoFactorEnabledAsync(user.Id); if (twoFactorEnabled) { var code = await userManager.GenerateTwoFactorTokenAsync(user.Id,"PhoneCode"); IdentityResult notificationResult = await userManager.NotifyTwoFactorTokenAsync(user.Id,"PhoneCode",code); if(!notificationResult.Succeeded){ //you can add your own validation here context.SetError(error,"Failed to send OTP"); } } // commented for clarification ClaimIdentity oAuthIdentity ..... // Commented for clarification AuthenticationProperties properties = CreateProperties(user); // Commented for clarification 在CreateProperties方法内部用userObject替换参数,如下所示: public static AuthenticationProperties CreateProperties(ApplicationUser user) { IDictionary<string,string> data = new Dictionary<string,string> { { "userId",user.Id },{ "requireOTP",user.TwoFactorEnabled.ToString() },} // commented for clarification } 以上代码检查用户是否启用了TFA,如果启用它将生成验证码并使用您选择的SMSService发送. 2.创建TwoFactorAuthorize属性 创建响应类ResponseData public class ResponseData { public int Code { get; set; } public string Message { get; set; } } 添加TwoFactorAuthorizeAttribute public override async Task OnAuthorizationAsync(HttpActionContext actionContext,System.Threading.CancellationToken cancellationToken) { #region Get userManager var userManager = HttpContext.Current.GetOwinContext().Get<ApplicationUserManager>(); if(userManager == null) { actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized,new ResponseData { Code = 100,Message = "Failed to authenticate user." }); return; } #endregion var principal = actionContext.RequestContext.Principal as ClaimsPrincipal; #region Get current user var user = await userManager.FindByNameAsync(principal?.Identity?.Name); if(user == null) { actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized,Message = "Failed to authenticate user." }); return; } #endregion #region Validate Two-Factor Authentication if (user.TwoFactorEnabled) { actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized,new ResponseData { Code = 101,Message = "User must be authenticated using Two-Factor Authentication." }); } #endregion return; } } 3.使用TwoFactorAuthorizeAttribute 在控制器中使用TwoFactorAuthorizeAttribute [Authorize] [TwoFactorAuthorize] public IHttpActionResult DoMagic(){ } 4.验证OTP [Authorize] [HttpGet] [Route("VerifyPhoneOTP/{code}")] public async Task<IHttpActionResult> VerifyPhoneOTP(string code) { try { bool verified = await UserManager.VerifyTwoFactorTokenAsync(User.Identity.GetUserId(),code); if (!verified) return BadRequest($"{code} is not a valid OTP,please verify and try again."); var result = await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId(),false); if (!result.Succeeded) { foreach (string error in result.Errors) errors.Add(error); return BadRequest(errors[0]); } return Ok("OTP verified successfully."); } catch (Exception exception) { // Log error here } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net-web-api – 带有PUT或PATCH谓词的ASP.NET 5 MVC 6
- asp.net-mvc-3 – 无法加载文件或程序集’StructureMap,Ver
- asp.net – 使用listview进行LINQ和分页
- asp.net-core – 如何检索当前响应体长度?
- 是否可以在OSX上使用Razor作为独立库(没有任何asp.net业务)
- asp.net-mvc – ASP.net MVC RTM测试命名约定
- 如何决定哪个是正确的,WebForms或MVC做ASP.NET时
- asp.net core 2.0 spa角谷歌地图
- asp.net-mvc-2 – 在MVC中实现自定义标识和IPrincipal
- asp.net – 如何将模型从一个局部视图传递到另一个局部视图