这是与此非常相似的问题 在确认电子邮件中 aspnet身份无效令牌 但是解决方案无效,因为我使用的是包含ASP.NET Core身份的新ASP.NET Core 1.0.
This is a very similar question to this aspnet identity invalid token on confirmation email but the solutions are not valid because I am using the new ASP.NET Core 1.0 that includes ASP.NET Core Identity.
我的情况如下:
在后端(ASP.NET Core)中,我有一个函数可以发送带有链接的密码重置电子邮件.为了生成该链接,我必须使用Identity生成一个代码.像这样的东西.
In the back end (ASP.NET Core) I have a function that sends a password reset email with a link. In order to generate that link I have to generate a code using Identity. Something like this. public async Task SendPasswordResetEmailAsync(string email) { //_userManager is an instance of UserManager<User> var userEntity = await _userManager.FindByNameAsync(email); var tokenGenerated = await _userManager.GeneratePasswordResetTokenAsync(userEntity); var link = Url.Action("MyAction", "MyController", new { email = email, code = tokenGenerated }, protocol: HttpContext.Request.Scheme); //this is my service that sends an email to the user containing the generated password reset link await _emailService.SendPasswordResetEmailAsync(userEntity , link); }
这将生成一封电子邮件,其中包含以下链接:
this would generate an email with a link to:
myapp:8080/passwordreset?code=CfDJ8JBnWaVj6h1PtqlmlJaH57r9TRA5j7Ij1BVyeBUpqX+5Cq1msu9zgkuI32Iz9x/5uE1B9fKFp4tZFFy6lBTseDFTHSJxwtGu+jHX5cajptUBiVqIChiwoTODh7ei4+MOkX7rdNVBMhG4jOZWqqtZ5J30gXr/JmltbYxqOp4JLs8V05BeKDbbVO/Fsq5+jebokKkR5HEJU+mQ5MLvNURsJKRBbI3qIllj1RByXt9mufGRE3wmQf2fgKBkAL6VsNgB8w==
然后,我的AngularJs应用程序将显示一个带有输入和确认新密码的表单的视图,并使用新密码和从URL中的查询参数获得的代码来放置JSON对象.
Then my AngularJs application would present a view with a form to enter and confirm the new password, and would PUT a JSON object with the new password and the code that got from the query parameter in the URL.
最后,我的后端将收到PUT请求,获取代码并使用Identity进行验证,如下所示:
Finally my back end would get the PUT request, grab the code and validate it using Identity like this:
[HttpPut] [AllowAnonymous] [Route("api/password/{email}")] public async Task<IActionResult> SendPasswordEmailResetRequestAsync(string email, [FromBody] PasswordReset passwordReset) { //some irrelevant validatoins here await _myIdentityWrapperService.ResetPasswordAsync(email, passwordReset.Password, passwordReset.Code); return Ok(); }
问题是身份以
无效的令牌
Invalid token
错误.我发现问题在于代码不匹配,并且上面的代码将在PUT请求的JSON对象中被接收回去,如下所示:
error. I have found that the problem is that the codes don't match and the above code would be received back in the JSON object in the PUT request as follows:
CfDJ8JBnWaVj6h1PtqlmlJaH57r9TRA5j7Ij1BVyeBUpqX 5Cq1msu9zgkuI32Iz9x/5uE1B9fKFp4tZFFy6lBTseDFTHSJxwtGu jHX5cajptUBiVqIChiwoTODh7ei4 MOkX7rdNVBMhG4jOZWqqtZ5J30gXr/JmltbYxqOp4JLs8V05BeKDbbVO/Fsq5 jebokKkR5HEJU mQ5MLvNURsJKRBbI3qIllj1RByXt9mufGRE3wmQf2fgKBkAL6VsNgB8w==请注意,现在有+个符号的地方有空格个符号,很显然,这使Identity认为令牌是不同的. 出于某种原因,Angular会以与编码不同的方式来解码URL查询参数.
Notice that where there was + symbols now there are spaces symbols and obviously that causes Identity to think the tokens are different. For some reason Angular is decoding the URL query parameter in a different way that was encoded.
该如何解决?
推荐答案此答案 stackoverflow/a/31297879/2948212 为我指明了正确的方向.但是正如我说的是用于其他版本的解决方案,现在它的解决方案略有不同.
This answer stackoverflow/a/31297879/2948212 pointed me in the right direction. But as I said it was for a different version and now it is slightly different solution.
答案仍然是相同的:以基本64 URL编码令牌,然后以基本64 URL解码令牌.这样,Angular和ASP.NET Core都将检索完全相同的代码.
The answer is still the same: encode the token in base 64 url, and then decode it in base 64 url. That way both Angular and ASP.NET Core will retrieve the very same code.
我需要为Microsoft.AspNetCore.WebUtilities;
现在代码将是这样的:
public async Task SendPasswordResetEmailAsync(string email) { //_userManager is an instance of UserManager<User> var userEntity = await _userManager.FindByNameAsync(email); var tokenGenerated = await _userManager.GeneratePasswordResetTokenAsync(userEntity); byte[] tokenGeneratedBytes = Encoding.UTF8.GetBytes(tokenGenerated); var codeEncoded = WebEncoders.Base64UrlEncode(tokenGeneratedBytes); var link = Url.Action("MyAction", "MyController", new { email = email, code = codeEncoded }, protocol: HttpContext.Request.Scheme); //this is my service that sends an email to the user containing the generated password reset link await _emailService.SendPasswordResetEmailAsync(userEntity , link); }以及在PUT请求期间接收回代码时
and when receiving back the code during the PUT request
[HttpPut] [AllowAnonymous] [Route("api/password/{email}")] public async Task<IActionResult> SendPasswordEmailResetRequestAsync(string email, [FromBody] PasswordReset passwordReset) { //some irrelevant validatoins here await _myIdentityWrapperService.ResetPasswordAsync(email, passwordReset.Password, passwordReset.Code); return Ok(); } //in MyIdentityWrapperService public async Task ResetPasswordAsync(string email, string password, string code) { var userEntity = await _userManager.FindByNameAsync(email); var codeDecodedBytes = WebEncoders.Base64UrlDecode(code); var codeDecoded = Encoding.UTF8.GetString(codeDecodedBytes); await _userManager.ResetPasswordAsync(userEntity, codeDecoded, password); }更多推荐
确认电子邮件中的ASP.NET Core身份无效令牌
发布评论