首页 文章

MVC 5反向代理验证并仅使用用户名来使用角色

提问于
浏览
2

我有一个MVC 5网络应用程序 . 目前,该应用程序正在使用个人帐户登录 . 还有授权的角色 . 用户使用其用户名和密码登录 .

问题是这样的 . 我需要对通过反向代理发送的用户请求进行身份验证和授权 .

enter image description here

  • 用户提出申请(反向代理网址) http://myapp.domain.com

  • 反向代理将进行其他调用,并验证用户是否有权访问应用内容 . (为简单起见,图中缺少) .

  • 如果用户一切正常,则将呼叫重定向到实际的MVC应用程序,其中请求将包含带有用户名的标头 .

  • MVC必须检查请求是否来自反向代理(没有问题,IP检查,以及作为标头发送的一些密钥 . )

  • MVC应该读取请求标头,获取用户名,对其进行身份验证并根据他拥有的角色对其进行授权 .

  • 如果请求没有具有适当的角色,则拒绝请求 . 示例用户是角色访问者,但他正在尝试访问管理员角色内容 .

我的问题在于当存在用户名时对请求进行身份验证和授权 .

由于应用程序已使用用户名和密码进行身份验证,我正在考虑执行以下操作:

  • 反向代理将请求发送到https://realapp.domain.com/account/login .

  • 在帐户控制器的操作登录中,我可以实现逻辑来读取请求并从标头中获取用户名

  • 此时我们知道用户X已经过身份验证,因为反向代理和其他系统会检查它 . 基本上所有到达的请求都被认为是安全的(来自反向代理服务器)

  • 如果数据库中不存在用户名(第一次调用应用程序),MVC应用程序将使用虚拟密码(Password123)创建用户 .

  • 如果用户名存在于数据库中,那么使用用户名和虚拟密码登录他 . 密码123 var result = await SignInManager.PasswordSignInAsync("username", "Password123", false, shouldLockout: false);

  • 用户已通过身份验证和授权 .

基本上我的想法是为每个用户设置相同的密码,以便在应用程序中对它们进行身份验证并使用角色 .

你怎么看?

1 回答

  • 2

    由于身份是基于声明的 . 您不需要任何密码甚至任何用户对象来验证用户 . 因此,在Identity中使用存储也是完全可选的 . 您只需创建一些声明并根据这些声明授权您的用户 . 考虑这个简单的例子作为线索:

    // imaging this action is called by proxy
    public ActionResoult Login()
    {
        // this custom method extract username from header and check IP and more
        var username=_myUserManager.GetUserName();
    
        if(username!=null)         
        {
    
            // optionally you have own user manager which returns roles from username
            // no matter how you store users and roles
            string[] roles=_myUserManager.GetUserRoles(username);
    
            // user is valid, going to authenticate user for my App
            var ident = new ClaimsIdentity(
                new[] 
                {  
                    // adding following 2 claim just for supporting default antiforgery provider
                    new Claim(ClaimTypes.NameIdentifier, username),
                    new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string"),
    
                    // an optional claim you could omit this 
                    new Claim(ClaimTypes.Name, username),
    
                    // populate assigned user's role form your DB 
                    // and add each one as a claim  
                    new Claim(ClaimTypes.Role, roles[0]),
                    new Claim(ClaimTypes.Role, roles[1]),
                    // and so on
                },
                DefaultAuthenticationTypes.ApplicationCookie);
    
            // Identity is sign in user based on claim don't matter 
            // how you generated it             
            HttpContext.GetOwinContext().Authentication.SignIn(
                new AuthenticationProperties { IsPersistent = false }, ident);
    
            // auth is succeed, without needing any password just claim based 
            return RedirectToAction("MyAction"); 
        }
        // invalid user        
        ModelState.AddModelError("", "We could not authorize you :(");
        return View();
    }
    

    现在我们没有任何密码授权我们的用户,所以我们也可以使用 Authorize 过滤器:

    [Authorize]
    public ActionResult Foo()
    {
    }
    
    // since we injected user roles to Identity we could do this as well
    [Authorize(Roles="admin")]
    public ActionResult Foo()
    {
        // since we injected our authentication mechanism to Identity pipeline 
        // we have access current user principal by calling also
        // HttpContext.User
    }
    

    注意:您的代理必须处理您的应用生成的Cookie并将其正确地提供给您的用户 . 由于您的应用基于cookie .

    您可以从我的Github仓库下载Token Based Authentication Sample,也可以阅读my other answer,这将关闭您的方案 .

相关问题