【问题标题】:Authentification and Authorization in ASP.NET MVC 5ASP.NET MVC 5 中的身份验证和授权
【发布时间】:2015-11-19 08:02:34
【问题描述】:

我对 ASP.NET MVC 5 中的身份验证和授权感到非常困惑。

我正在开发一个现有网站,我需要在其中添加安全性。安全性是指身份验证(登录)和授权(角色)。我可以访问 Web 服务,但不能直接访问数据库,尽管我可以访问实体(用户、角色等)。

Membership Provider 似乎有点老了,所以我看了一下 Identity,但在现有项目中实现它看起来很复杂,尤其是当我无法直接访问数据库时。

什么是好的解决方案?最佳做法是什么? 你能建议我任何好的资源,以便我可以满足我的需要吗?

谢谢。

【问题讨论】:

    标签: asp.net-mvc authentication asp.net-mvc-5 authorization asp.net-identity


    【解决方案1】:

    如果有人像我一样感到迷茫,这里有一个使用 Claims 的潜在解决方案。最后,您将知道如何处理身份验证、授权和角色。 希望这能有所帮助。

    启动配置

    在我的项目的根文件夹中,我创建了一个文件,startup.cs。她包含一个部分类,我们将使用它来配置应用程序以使用存储签名用户的 cookie。

    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
        }
    }
    

    然后,在 App_Start 我有一个文件 Startup.Auth.cs

    public partial class Startup
    {
        public void ConfigureAuth(IAppBuilder app)
        {
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login")                
            });
        }
    }
    

    控制器

    首先,我创建了一个具有 IAuthenticationManager 类型属性的 AcountController.cs。此属性获取当前请求可用的身份验证中间件功能。

    public class CompteController : Controller
    { 
        private IAuthenticationManager AuthenticationManager
        {
            get
            {
                return HttpContext.GetOwinContext().Authentication;
            }
        }
    }
    

    然后,我有一个经典视图,称为使用 GET 和 POST 登录。在帖子中,如果用户可以登录,我会检查我的 Web 服务。如果他可以,我会调用一个魔法函数来进行身份验证。在这段代码中,用户类是我在 Web 服务中获得的自定义用户。他没有实现 IUser。

    private void AuthentifyUser(User user, bool isPersistent)
    {  
        AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
    
        CustomIdentity identity = new CustomIdentity(user);
        CustomPrincipal principal = new CustomPrincipal(identity);
        Thread.CurrentPrincipal = principal;
    
        AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
    }
    

    我的控制器中最后一个重要的方法允许用户注销。

    public ActionResult Deconnexion()
    {
        AuthenticationManager.SignOut();
        return RedirectToAction("Login", "Account");
    }
    

    索赔

    CustomIdentity 和 CustomPrincipal 是我用于 Claims 系统的两个自定义类。它们间接实现了 IIdentity 和 IPrincipal。我把它们放在一个单独的新文件夹中。

    -请记住,主体对象表示代表其运行代码的用户的安全上下文,包括该用户的身份 (IIdentity) 以及他们所属的任何角色。

    -一个身份对象代表代码正在代表其运行的用户。

    public class HosteamIdentity : ClaimsIdentity
    {
        public HosteamIdentity(User user)
            : base(DefaultAuthenticationTypes.ApplicationCookie)
        {
            AddClaim(new Claim("IdUser", user.Id.ToString()));           
            AddClaim(new Claim(ClaimTypes.Name, user.Name));
            AddClaim(new Claim(ClaimTypes.Role, user.Role));
        }
    
        public int IdUser 
        { 
            get
            {
                return Convert.ToInt32(FindFirst("IdUser").Value);
            }
        }
    
        //Other Getters to facilitate acces to the Claims.
    }
    

    委托人允许我们访问身份。

    public class HosteamPrincipal : ClaimsPrincipal
    {
        private readonly HosteamIdentity _identity;
        public new HosteamIdentity Identity
        {
            get { return _identity; }
        }
    
    
        public HosteamPrincipal(HosteamIdentity identity)
        {
            _identity = identity;
        }  
    
        public override bool IsInRole(string role)
        {
            return _identity.Role == role;
        }
    }
    

    访问 CustomPrincipal

    现在,我将转到 gGlobal.asax,在这里我们将覆盖 Application_PostAuthenticateRequest 事件。当安全模块建立用户身份时触发此事件。

    我们将使用 Thread.CurrentPrincipal,这个静态对象获取或设置线程的当前主体(用于基于角色的安全性),因此它非常适合我们的情况!

    您可能需要在此处调整代码。我个人必须请求我的 Web 服务,这可能不是你的情况。

    只是简单地谈谈我们的构造函数。拳头是空的,不关心角色的时候就用它

    protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
        {
            if (HttpContext.Current.User.Identity.IsAuthenticated)
            {
               Thread.CurrentPrincipal = new HosteamPrincipal(
                    new HosteamIdentity(
                        WebService.GetUser(
                            HttpContext.Current.User.Identity.Name)));            
            }
        }
    

    在大多数情况下,按名称检索用户并不是一个好习惯。请根据您的解决方案调整上述代码。

    授权属性过滤器

    现在,如果我们能够轻松地判断出经过身份验证的用户可以访问哪个控制器或动作,那就太好了。为此,我们将使用过滤器。

    过滤器是自定义类,它们提供了一种声明性和编程方式来向控制器操作方法添加操作前和操作后行为。我们使用它们作为注解,例如 [Authorize] 是一个过滤器。

    由于要解释的东西很多,我让你看一下cmets,它们非常明确。

    只是简单地谈谈我们的构造函数。 -第一个是空的,我们不关心 Roles 的时候会用到。我们通过在 Controller 或 Action 上编写注释 [CustomAuthorize] 来访问它。 -第二个,接受一个角色数组,我们将通过编写注释来使用它 [CustomAuthorize("Role1", "Role2", etc.)] 一个控制器或一个动作。他将定义哪些角色可以访问控制器或操作

    public class CustomAuthorize : AuthorizeAttribute
    {
        private new string[] Roles { get; set; }
    
    
        public CustomAuthorize() { }
        public CustomAuthorize(params string[] roles)
        {
            this.Roles = roles[0].Split(',');
        }
    
    
        /// <summary>
        /// Check for Authorizations (Authenticated, Roles etc.)
        /// </summary>
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (httpContext.Request.IsAuthenticated)
                if (Roles != null)
                {
                    foreach (string role in Roles)
                        if (((HosteamPrincipal)Thread.CurrentPrincipal).IsInRole(role))
                            return true;
                    return false;            
                }
                else                    
                    return true;
            return false;
        }
    
    
        /// <summary>
        /// Defines actions to do when Authorizations are given or declined
        /// </summary>
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (!AuthorizeCore(filterContext.HttpContext))
                HandleUnauthorizedRequest(filterContext);
        }
    
    
        /// <summary>
        /// Manage when an Authorization is declined
        /// </summary>
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsAuthenticated)
                filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden);
            else
                base.HandleUnauthorizedRequest(filterContext);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多