MVC5 EF6如何在提交数据之前添加带有附加身份验证的确认屏幕

时间:2014-03-24 16:20:08

标签: authentication asp.net-mvc-5 asp.net-mvc-viewmodel

开发一个新的MVC5项目。我有用于CRUD功能的脚手架,但是要求在插入或更新数据时,需要电子签名。在将数据提交到数据库之前,必须向用户显示一个页面,要求他们再次输入用户名和密码以确认数据。如果输入的用户名和密码有效且用户名与当前登录的用户匹配,则输入的原始数据可以保存到其表(例如成员)中,电子签名信息将保存到单独的表(ESignature)中。我感谢任何关于最佳方式的帮助 - 一个结合了Member和ESignature的视图模型,或者从Account控制器重用LoginViewModel来检查身份验证,还是另一种方法?我需要能够在需要电子签名的六个控制器中使用的东西。

1 个答案:

答案 0 :(得分:0)

好吧也许我的方法不是最好的,但我会尝试。

我的解决方案是创建CustomAttributeAuthorizeAttribute并装饰所有需要Esignature的操作。在CustomAttribute实现中,您将重定向到与Login非常相似的控制器操作,但稍作修改。

public class CustomAuthorize : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);

            var url = filterContext.HttpContext.Request.Url;
            var query = url.Query;
            if (query.Contains("g="))
            {
                var code = query.Split(new String[] { "g=" }, StringSplitOptions.None);
                //You can create time sensistive token and validate it.
            }
            else
            {
                //Redirect User to a particular page
                filterContext.Result = new RedirectToRouteResult(
                                        new RouteValueDictionary 
                                    {                                    
                                    { "controller", "Account" },
                                    { "action", "elogin" },
                                    { "redirectUrl", url.AbsolutePath}
                                    }
                );
            }
        }

    }

然后用它装饰例如Index()方法。

[CustomAuthorize]
public ActionResult Index()
{
  return View();
}

首先,当您点击Index()方法然后在OnAuthorization CustomAuthorizeAttribute方法内执行else循环时,会将您重定向到elogin内的AccountController方法}。此方法类似于Login HttpGet方法。在指定RedirectToResult时,我指定当前页面的redirectUrl路径,因此当您在elogin方法中成功验证用户时,在redirectUrl的帮助下,我们可以返回。

 [AllowAnonymous]
        public ActionResult ELogin(string returnUrl)
        {
            ViewBag.ReturnUrl = returnUrl;
            return View("Login");
        }

        //
        // POST: /Account/Login
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> ELogin(LoginViewModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                var user = await UserManager.FindAsync(model.UserName, model.Password);
                if (user != null)
                {
                    await SignInAsync(user, model.RememberMe);
                    var url =  String.Format("{0}/?g={1}", returnUrl, "HashCode");
                    return RedirectToLocal(url);
                }
                else
                {
                    ModelState.AddModelError("", "Invalid username or password.");
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

HttpPost ELogin方法的唯一区别在于,在执行RedirectToLocal之前,我追加/ g = HasCode。注意:在这里,您可以附加自己的逻辑来创建时间敏感的哈希。当我们被重定向到我们的主页时,如果网址包含g = HashCode,我们可以在OnAuthorization方法内部进行检查,然后不要重定向到登录页面。

这对于如何强制用户在遇到特定控制器时重新登录是非常基本的想法。您将不得不进行额外的安全检查,并小心您通过URL公开的内容。