ASP.NET MVC中的身份验证和授权5

时间:2015-08-25 14:38:49

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

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

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

成员资格提供程序似乎有点旧,所以我看了一下Identity,但实现现有项目看起来很复杂,特别是当我无法直接访问数据库时。

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

谢谢。

1 个答案:

答案 0 :(得分:2)

如果有人感到像我一样迷失,这是一个使用声明的潜在解决方案。最后,您将了解如何处理身份验证,授权和角色。 希望这可以提供帮助。

启动配置

在我的项目的根文件夹中,我创建了一个文件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;
        }
    }
}

然后,我有一个名为Login with GET和POST的经典视图。如果用户可以登录,我会在帖子中检查我的Web服务。如果他能,我称之为神奇功能进行身份验证。在此代码中,类User是我在Webservice中获得的自定义用户。他没有实施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);
}

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

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

在大多数情况下,通过名称检索用户不是一个好习惯。请将上述代码改编为您的解决方案。

授权属性过滤器

现在,如果我们能够轻松地告知经过身份验证的用户可以访问哪个Controller或Action,那将会很棒。为此,我们将使用过滤器。

过滤器是自定义类,它提供声明式和编程式方法,以便为控制器操作方法添加操作前和操作后行为。我们将它们用作注释,例如[Authorize]是一个过滤器。

由于需要解释许多事情,我会让你阅读评论,它们非常明确。

简单谈谈我们的构造函数。 - 第一个是空的,当我们不关心角色时我们会使用它。我们通过编写注释[CustomAuthorize]来使用Controller或Action。来访问它 - 第二个,采用一系列角色,我们将通过编写注释[CustomAuthorize(" Role1"," Role2"等)]来使用它。或行动。他将定义哪些角色访问控制器或操作

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