【问题标题】:Re-authenticate User in MVC application for Action在 MVC 应用程序中重新验证用户以执行操作
【发布时间】:2013-09-30 09:59:30
【问题描述】:

如何强制用户在 MVC 中执行操作之前重新进行身份验证?

我们正在使用 Windows 身份验证。我们希望确保用户正在执行一些操作(并在用户忘记锁定其工作站时阻止其他用户执行这些操作)。

理想情况下,我只能编写一个扩展 Authorize 的属性:

namespace AuthTest.Controllers
{
    [Authorize(Roles="MyApp")]
    public class HomeController : Controller
    {    
        public ActionResult Index()
        {
             // A regular action
            return View();
        } 

        [ReAuthenticate]
        public ActionResult CriticalAction()
        {
            // Do something important
            return View();
        }
     }
}

看来我可以强制用户重新输入他们的凭据,方法是让自定义ReAuthenticate 属性在AuthorizeCore 方法中发出HTTP 401 响应。然而,这需要一些技巧,因为Html.ActionLink 发送了两个请求:

protected override bool AuthorizeCore(HttpContextBase httpContext)
{
    bool ok = base.AuthorizeCore(httpContext);
    if (!ok) return false;

    if (httpContext.Session["ReAuthCnt"] == null)
    {
        httpContext.Session["ReAuthCnt"] = 1;
        return false;
    }
    else if ((int) httpContext.Session["ReAuthCnt"] < 2)
    {
        httpContext.Session["ReAuthCnt"] = (int)httpContext.Session["ReAuthCnt"] + 1;
        return false;
    }
    else
    {
        httpContext.Session["ReAuthCnt"]  = 0;
        return true;
    }
}

有没有更好的方法来完成重新授权?

【问题讨论】:

  • 重新认证是什么意思?
  • 您为什么要这样做?如果用户经过身份验证,那么他们就是经过身份验证的。如果您无法维护身份验证,您可以考虑使用 OAuth。或许如果您再多描述一下您的问题,我们可以提出建议。
  • 我已经更新了问题,提供了有关场景和我尝试过的更多细节。
  • 嗯,我理解他想要达到的目标,我正在尝试实现类似的目标。我需要让用户重新输入他们的网络密码并对其进行身份验证。这样做的原因是我想用该用户授权对 PDF 进行数字签名。如上所述,通过身份验证不足以让某些机构接受数字签名,因为人们经常将工作站解锁,因此需要对数字签名进行重新身份验证。我还没有尝试解决这个问题,我只是在寻找一些方向,如果我这样做了,我会回复。
  • 如何使用 ADFS 或某些联合身份验证在 Web 应用程序中再次对用户进行身份验证,以便您可以使用相同的凭据,尽管需要重新进行身份验证。

标签: asp.net-mvc asp.net-mvc-4 authentication windows-authentication


【解决方案1】:

我会以不同的方式处理这个问题。听起来您真正想要的是临时证书提升,类似于 UAC 或 Sudo,但在您的网站上。如果经过一定时间,您可能希望用户必须再次输入其凭据才能访问这些功能。

我将采用的方法是创建一个自定义 IPrincipal,它允许您临时向用户添加特定角色,并在一段时间后使该角色过期。这不会与存储在数据库中的用户分配的角色相关联,除了可能说只有具有特定角色的用户可以提升。

这样,您可以简单地执行密码检查,将角色临时添加到用户角色列表中,然后标准授权属性将允许他们进入。

【讨论】:

    【解决方案2】:

    如果企业允许您实际使用表单重新验证他们(换句话说,有一个他们输入用户名和密码的页面),那么您可以执行以下操作。

    重新授权属性

    // custom page where user does type user/pass
    private string revalidateLoginUrl = "/account/reauth";
    private bool? hasReauthenticated = false;
    
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
      var authUrl = HttpContext.Request.Url;
      hasReauthenticated = httpContext.Session[authUrl] as bool?
    
      // could be just (hasReauthenticated)
      // this look a bit more readable
      return (hasReauthenticated == true);
    }
    
    public override void OnAuthorization(AuthorizationContext filterContext) 
    {
      if (filterContext == null) 
      {
        throw new ArgumentNullException("filterContext");
      }
    
      var isAuthorized = AuthorizeCore(filterContext.HttpContext);
    
      var authUrl = filterContext.HttpContext.Request.Url;
      filterContext.HttpContext.Session[authUrl] = false;
    
      if (!isAuthorized) 
      {
        HandleUnauthorizedRequest(filterContext);
      }
    }
    
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
      // something like this
      var fullUrl = validateLoginurl + "?returnUrl=" 
        + HttpUtility.UrlEncode(revalidaetLoginUrl);
    
      filterContext.HttpContext.Response.Redirect(validateLoginUrl);
    }
    

    ReauthModel

    public class ReauthModel
    {
      public string Username { get; set; }
      public string Password { get; set; }
      public string ReturnUrl { get; set; }
    }
    

    AccountController.cs (Validate a username and password against Active Directory?)

    using System.DirectoryServices.AccountManagement;
    
    public ActionResult Reauth(string returnUrl)
    {
      var model = new ReauthModel();
      model.ReturnUrl = returnUrl;
    
      return View(model);
    }
    
    [ValidateAntiForgeryToken]
    public ActionResult Reauth(ReauthModel model)
    {
      using(PrincipalContext pc = new 
        PrincipalContext(ContextType.Domain, "YOURDOMAIN"))
      {
        // validate the credentials
        bool isValid = pc.ValidateCredentials("myuser", "mypassword");
        if (isValid)
        {
          Session[model.ReturnUrl] = true;
          return RedirectTolocal(model.ReturnUrl);
        }
      }
    
      // not authenticated
      return RedirectToAction("?");
    
      //or
      model.Username = string.Empty;
      model.Passsword = string.Empty;
    
      return View(model);
    }
    

    我认为您可以根据 ReauthModel 想象视图的外观。

    注意:这应该您正在使用的任何其他授权属性一起使用,而不是代替。由于用户在网站上输入用户名和密码,因此需要使用 SSL(即使它是内部的)。

    【讨论】:

      【解决方案3】:

      你可以从这里得到想法,我在这里做角色基础授权

      [Authorize(Roles = "admin,superadmin")]//Controler Authorization
              public class ControlController : Controller
              {
      
                  [Authorize(Roles = "superadmin")]//action Authorization
                  public ActionResult youraction()
                  {
                      return View();
                  }
            }
      

      【讨论】:

        【解决方案4】:

        如果用户正在执行 POST,您能否在该表单中添加用户名和密码字段,然后在控制器中或使用 ActionFilter 针对 Active Directory 验证凭据?

        【讨论】:

          猜你喜欢
          • 2011-11-26
          • 1970-01-01
          • 2012-12-12
          • 1970-01-01
          • 1970-01-01
          • 2015-08-15
          • 1970-01-01
          • 2019-07-22
          • 1970-01-01
          相关资源
          最近更新 更多