asp.net 在WebApi中生成重置密码链接

ejk8hzay  于 2023-01-18  发布在  .NET
关注(0)|答案(5)|浏览(176)

我想生成一个重置密码链接,发送到用户的电子邮件,该链接将打开“重置密码”页。在此页上,我将填写有关新密码的详细信息,然后确认密码。
为此,我遵循了Link
但是有一个Url.Action方法,我在我的API项目中找不到。

var callbackUrl = Url.Action(
               "ConfirmEmail", "Account", 
               new { userId = user.Id, code = code }, 
               protocol: Request.Url.Scheme);

有没有人在网页API中做了重置密码的部分?我需要一些帮助。

lymnna71

lymnna711#

您可以在Web API 2.0中使用Url.Link

var callbackUrl = Url.Link("Default", new { Controller = "Account", 
                  Action = "ConfirmEmail", userId = user.Id, code = code });
ar7v8xwq

ar7v8xwq2#

Url.Action不存在,因为WebApi中的Url帮助器没有Action方法。您可以使用Url.Route生成相同的内容,但您需要创建一个命名路由才能使用该方法。如果您正在使用属性路由它,则可以向路由属性添加一个名称,如下所示:

[Route(Name="ConfirmEmail")]

而助手就是

var callbackUrl = Url.Route("ConfirmEmail", new { userId = user.Id, code = code });
hjzp0vay

hjzp0vay3#

我创建了一个简单的“更改密码”表单,通过单击webAPI应用程序中的菜单进行管理。在此表单的更新处理程序上,我创建了以下事件处理程序。这只是调用VS2013 WebAPI模板附带的AccountController Web服务。此示例启用了身份验证,并注意用于在AccountController方法中包含已定义路由的特定URL。
在WebAPI模板中生成的AccountController类中查找ChangePassword()方法,看看调用了什么。我认为这应该回答了您的基本问题。

function updateHandler(callback) {
var response;
var targetUrl;

// disabled the login button to avoid multiple events
$("#btnLogin").prop('disabled', true);

var loginData = {
    grant_type: 'password',
    NewPassword: $("#txtNewPassword").val(),
    OldPassword: $("#txtOldPassword").val(),
    ConfirmPassword: $("#txtConfirmPassword").val()
};

var token = sessionStorage.getItem(tokenKey);
var headers = {};
if (token) {
    headers.Authorization = 'Bearer ' + token;
}

targetUrl = "/api/account/ChangePassword";

$.ajax({
    type: 'POST',
    url: targetUrl,
    data: loginData,
    headers: headers,
}).done(function (data) {
        closeChangePassword();
}).fail(function (xhr, textStatus, errorThrown) {
    passwordErrorHandler(xhr,0);
    // re-enable the login button 
    $("#btnLogin").prop('disabled', false);
});

}

xriantvc

xriantvc4#

在我看来,你永远不应该使用Url.Link()Url.Action()来发送东西给一个没有自己设置主机的用户,你是在把他们暴露给一个可能的Host Header Attack -> Password Reset Poisoning
如果IIS有一个绑定接受80/443上的连接,主机头可以被更改,从而影响Url.Link()Url.Action()方法。如果你看我下面的请求,我连接到http://hostheaderattack,但操纵host头。
概念验证(PoC):
Url.Link:

public class TestController : ApiController
{
    public IHttpActionResult Get()
    {
        var callbackUrl = Url.Link("Default", new
        {
            Controller = "Home",
            Action = "Index",
        });

        return Ok(callbackUrl);
    }
}

Url.Action:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        ViewBag.Title = $"Url Created: {Url.Action("Index", "Home", "", Request.Url.Scheme)}";

        return View();
    }
}

我在这里也证明了这一点:
https://security.stackexchange.com/questions/170755/host-header-attack-password-reset-poisoning-asp-net-web-api-2-hosted-as-az/170759#170759
更多关于主机头攻击的阅读:
https://www.acunetix.com/blog/articles/automated-detection-of-host-header-attacks/
你应该做的是永远不要相信用户请求,并手动构造带有主机的url。
手动主机名示例:
操作URL:Url.Action("Index", "Home", null, Request.Url.Scheme, "example.com")
对于Url.Link,这有点麻烦,但可以这样做:

public class TestController : ApiController
{
    // GET api/<controller>
    public IHttpActionResult Get()
    {
        var callbackUrl = Url.Link("Default", new
        {
            Controller = "Home",
            Action = "Index",
        });

        callbackUrl = ReplaceHost(callbackUrl, "example.com");

        return Ok(callbackUrl);
    }

    private string ReplaceHost(string original, string newHostName)
    {
        var builder = new UriBuilder(original);
        builder.Host = newHostName;
        return builder.Uri.ToString();
    }
}

ReplaceHost方法的源代码:
https://stackoverflow.com/a/479812/3850405

v440hwme

v440hwme5#

尝试以下操作:

var code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
        var callbackUrl = Url.Action("ResetPassword", "Account", 
        new { UserId = user.Id, code = code }, protocol: Request.Url.Scheme);
        await UserManager.SendEmailAsync(user.Id, "Reset Password", 
        "Please reset your password by clicking here: <a href=\"" + callbackUrl + "\">link</a>");        
        return View("ForgotPasswordConfirmation");

代码来源于"Account confirmation and password recovery with ASP.NET Identity (C#)"。

相关问题