首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ASP.NET MVC 5中的认证与授权

ASP.NET MVC 5中的认证与授权
EN

Stack Overflow用户
提问于 2015-08-25 14:38:49
回答 1查看 2K关注 0票数 1

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

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

成员资格提供程序似乎有点老了,所以我看了一下标识,但是实现现有项目似乎很复杂,特别是当我没有直接访问数据库的时候。

什么是好的解决方案?什么是最佳做法?你能给我推荐什么好的资源来满足我的需要吗?

谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-09-07 08:26:21

如果有人和我一样感到迷茫,下面是一个使用索赔的潜在解决方案。最后,您将知道如何处理身份验证、授权和角色。希望这能帮上忙。

启动配置

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

代码语言:javascript
复制
public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        ConfigureAuth(app);
    }
}

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

代码语言:javascript
复制
public partial class Startup
{
    public void ConfigureAuth(IAppBuilder app)
    {
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login")                
        });
    }
}

控制器

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

代码语言:javascript
复制
public class CompteController : Controller
{ 
    private IAuthenticationManager AuthenticationManager
    {
        get
        {
            return HttpContext.GetOwinContext().Authentication;
        }
    }
}

然后,我有一个叫做Login和GET和POST的经典视图。在这篇文章中,我签入了我的Webservice,如果用户可以登录。如果可以的话,我会调用魔法函数来验证。在这段代码中,类用户是我在Webservice中获得的自定义用户。他没有实现IUser。

代码语言:javascript
复制
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);
}

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

代码语言:javascript
复制
public ActionResult Deconnexion()
{
    AuthenticationManager.SignOut();
    return RedirectToAction("Login", "Account");
}

索赔

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

-Remember,一个主体对象表示代码所代表的用户的安全上下文,包括该用户的标识(IIdentity)和他们所属的任何角色。

-An identity对象代表代码运行的用户。

代码语言:javascript
复制
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.
}

校长让我们获得身份。

代码语言:javascript
复制
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

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

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

您可能需要修改这里的代码。我个人必须请求我的Webservice,这可能不是你的情况。

只是简单谈谈我们的建设者。拳头是空的,当我们不关心角色时,我们会使用它

代码语言:javascript
复制
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)));            
        }
    }

在大多数情况下,按is名称检索用户并不是一个好做法。请根据您的解决方案修改上述代码。

授权属性筛选器

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

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

由于有很多事情要解释,我会让你读一下评论,它们非常明确。

只是简单谈谈我们的建设者。-The第一个是空的,当我们不关心角色时,我们将使用它。我们通过编写注释CustomAuthorize访问控制器或操作。-The第二个角色数组,我们将通过编写注释CustomAuthorize("Role1“、"Role2”等)来使用它。使控制员或行动失去能力。他将定义哪些角色访问控制器或操作

代码语言:javascript
复制
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);
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32207009

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档