身份验证 – 如何使用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核心 – 如何在ASP.NET vNext MVC中实现会话状态6
- asp.net – 仅允许匿名用户通过web.config授权
- 混合WebForms/ASP.NET MVC
- asp.net-mvc – 如何在Razor帮助器中使用UrlHelper?
- asp.net – Global.asax PostAuthenticateRequest事件绑定是
- asp.net-mvc – 为什么我的动作方法不会超时?
- asp.net mvc路由id参数
- asp.net-mvc-2 – 在Visual Studio 2010 RC中更改默认浏览器
- 在ASP.NET中如何识别/处理404异常?
- 在ASP.NET中使用Visual Studio发布功能有什么好处?
