7

如何在 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发出HTTP 401响应来强制用户重新输入他们的凭据。AuthorizeCore但是,这需要一些技巧,因为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;
    }
}

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

4

4 回答 4

0

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

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

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

于 2015-01-30T22:19:29.830 回答
0

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

重新授权属性

// 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);
}

模型

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

AccountController.cs(针对 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(即使它是内部的)。

于 2015-01-30T20:35:10.430 回答
0

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

于 2013-12-31T20:08:13.490 回答
-2

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

[Authorize(Roles = "admin,superadmin")]//Controler Authorization
        public class ControlController : Controller
        {

            [Authorize(Roles = "superadmin")]//action Authorization
            public ActionResult youraction()
            {
                return View();
            }
      }
于 2015-01-30T19:19:22.957 回答