简体   繁体   English

所以非常非常混淆asp.net mvc中的身份验证

[英]So very very confused about Authentication in asp.net mvc

I come to the conclusion I need to ditch the ASP.NET Membership (for list of reasons). 我得出结论我需要抛弃ASP.NET Membership (出于原因列表)。

Now really the only thing I see that I need is creating a cookie(done by Form Authentication ), custom methods for authentication (done) and finally validation based on if they are logged in or by role. 现在我真正唯一需要的是创建一个cookie(由Form Authentication完成),自定义Form Authentication方法(完成),最后根据他们是登录还是按角色进行验证。

I am stuck on the last one. 我被困在最后一个。

I am trying to override the Authorize (attribute) but I have no clue how to do this. 我试图覆盖Authorize (属性),但我不知道如何做到这一点。 I looked at many examples and each one seems to be done differently then the next. 我看了很多例子,每个例子的表现与下一个不同。 I don't know why they do this or which one I should be using. 我不知道为什么他们这样做或我应该使用哪一个。

Some tutorials seem to do the authentication in the AuthorizeCore , Some do it in the OnAuthentication . 有些教程似乎在AuthorizeCore进行身份验证,有些教程在OnAuthentication

Some use some AuthorizationContext thing and then call this base class. 有些人使用一些AuthorizationContext ,然后调用这个基类。

base.OnAuthorization(filterContext);

Some seem to do caching in it. 有些人似乎在做缓存。

What I want is all the functionality the built in ones have but just hooked up to my custom tables. 我想要的是内置的所有功能,但只是连接到我的自定义表。 Like I going to have my own Role table. 就像我将拥有自己的角色表一样。 I need to tell it where that is and pull the stuff in. 我需要告诉它在哪里并拉进去。

Also I have no clue how to do this or how decorate the tag like this 此外,我不知道如何做到这一点或如何装饰这样的标签

[Authorize(Roles="test")]

References:- http://darioquintana.com.ar/blogging/tag/aspnet-mvc/ asp.net mvc Adding to the AUTHORIZE attribute http://davidhayden.com/blog/dave/archive/2009/04/09/CustomAuthorizationASPNETMVCFrameworkAuthorizeAttribute.aspx 参考文献: - http://darioquintana.com.ar/blogging/tag/aspnet-mvc/ asp.net mvc添加到AUTHORIZE属性 http://davidhayden.com/blog/dave/archive/2009/04/09/ CustomAuthorizationASPNETMVCFrameworkAuthorizeAttribute.aspx

Edit 编辑

This is what I have now. 这就是我现在拥有的。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public sealed class AuthorizeAttributeCustom : AuthorizeAttribute
    {

        public string Roles { get; set; }


        private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus)
        {
            validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
        }

        public override void OnAuthorization(AuthorizationContext filterContext)
        {

            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }

            if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
            {
                // auth failed, redirect to login page
                filterContext.Result = new HttpUnauthorizedResult();
                return;
            }

            DataClasses1DataContext test = new DataClasses1DataContext();
            var name = filterContext.HttpContext.User.Identity.Name;
            var user = test.User2s.Where(u => u.userName == name).FirstOrDefault();
            var role = test.Roles.Where(u => u.UserId == user.userId).Select(u => u.Role1).FirstOrDefault();

            string[] split = Roles.Split(',');

            if (split.Contains(role) == true)
            {
                // is authenticated and is in the required role
                SetCachePolicy(filterContext);
                return;
            }
            filterContext.Result = new HttpUnauthorizedResult();
        }

        private void SetCachePolicy(AuthorizationContext filterContext)
        {
            // ** IMPORTANT **
            // Since we're performing authorization at the action level, the authorization code runs
            // after the output caching module. In the worst case this could allow an authorized user
            // to cause the page to be cached, then an unauthorized user would later be served the
            // cached page. We work around this by telling proxies not to cache the sensitive page,
            // then we hook our custom authorization code into the caching mechanism so that we have
            // the final say on whether a page should be served from the cache.
            HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
            cachePolicy.SetProxyMaxAge(new TimeSpan(0));
            cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
        }
    }

Out Standing Questions 突出问题

  1. Why is it sealed? 为什么密封? If it is sealed does it not make it harder to unit test? 如果它是密封的,它是否会使单元测试更难?
  2. What is filterContext? 什么是filterContext?
  3. Why is no AuthorizeCore used? 为什么没有使用AuthorizeCore? Only OnAuthentication? 只有OnAuthentication?
  4. Whats the cache refering to? 什么是缓存参考? Like is it caching the role? 就像它缓存角色一样? Or the Page? 还是页面? I can't tell with the debugger it seems to run the code every single time. 我无法告诉调试器它似乎每次运行代码。

  5. Is caching it safe? 缓存安全吗?

  6. In general is this safe(ie no holes in it to be explioted- kinda worried I will screw something up and have some major hole in my site). 一般情况下这是安全的(即没有漏洞可以说明 - 有点担心我会搞砸一些东西并在我的网站上有一些重要的漏洞)。

Here's a custom attribute that would work just as you want it; 这是一个自定义属性,可以按照您的需要工作; using an Enum for role types and using cookie creation yourself, which allows for storing of roles. 使用Enum作为角色类型并自己使用cookie创建,允许存储角色。

usage 用法

  [AuthorizeAttributeCustom(RoleRequired = GoodRoles.YourRoleTypeHere)]

attribute code: 属性代码:

//http://stackoverflow.com/questions/977071/redirecting-unauthorized-controller-in-asp-net-mvc/977112#977112
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public sealed class AuthorizeAttributeCustom : AuthorizeAttribute
    {

        /// <summary>
        /// The name of the view to render on authorization failure.  Default is "Error".
        /// </summary>
        public string ViewName { get; set; }
        public ViewDataDictionary ViewDataDictionary { get; set; }
        public DeniedAccessView DeniedAccessView { get; set; }

        private GoodRoles roleRequired = GoodRoles.None;
        public GoodRoles RoleRequired { get{ return roleRequired;} set{ roleRequired = value;} } // this may evolve into sets and intersections with an array but KISS

        public AuthorizeAttributeCustom()
        {
            ViewName = "DeniedAccess";
            DeniedAccessView = new DeniedAccessView
                                   {
                                       FriendlyName = "n/a",
                                       Message = "You do not have sufficient privileges for this operation."
                                   };
            ViewDataDictionary = new ViewDataDictionary(DeniedAccessView);
        }

        private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus)
        {
            validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
        }


        public override void OnAuthorization(AuthorizationContext filterContext)
        {

            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }

            if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
            {
                // auth failed, redirect to login page
                filterContext.Result = new HttpUnauthorizedResult();
                return;
            }

            if (RoleRequired == GoodRoles.None || filterContext.HttpContext.User.IsInRole(RoleRequired.ToString()))
            {
                // is authenticated and is in the required role
                SetCachePolicy(filterContext);
                return;
            }

            filterContext.Result = new ViewResult { ViewName = ViewName, ViewData = ViewDataDictionary };
        }

        private void SetCachePolicy(AuthorizationContext filterContext)
        {
            // ** IMPORTANT **
            // Since we're performing authorization at the action level, the authorization code runs
            // after the output caching module. In the worst case this could allow an authorized user
            // to cause the page to be cached, then an unauthorized user would later be served the
            // cached page. We work around this by telling proxies not to cache the sensitive page,
            // then we hook our custom authorization code into the caching mechanism so that we have
            // the final say on whether a page should be served from the cache.
            HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
            cachePolicy.SetProxyMaxAge(new TimeSpan(0));
            cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
        }


    }

you'll need to have explicitly added your roles to auth cookie and read them back in a base controller say. 你需要明确地将你的角色添加到auth cookie并在基本控制器中读回来说。 my implementation has other details which you might not want so maybe best to read here: http://ondotnet.com/pub/a/dotnet/2004/02/02/effectiveformsauth.html 我的实现有你可能不想要的其他细节,所以最好在这里阅读: http//ondotnet.com/pub/a/dotnet/2004/02/02/effectiveformsauth.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM