如何使用证书而不是密码进行身份验证?

Dav*_*Can 7 c# asp.net authentication asp.net-mvc

我有一个小的C#MVC5应用程序,我正在构建并准备添加用户安全模块.(之前我刚刚创建了一个用于测试角色的会话变量)但是,我的安全需求不适合我见过的任何预构建的安全模块,即SimpleMembership等.

以下是我的情况和需求的摘要:

  • 没有密码-用户名/密码身份验证是容许

  • 用户使用带有客户端证书的智能卡在Web服务器级别进行身份验证 - 我不管理服务器,也永远不会看到他们的卡

  • IIS填充了Request.ClientCertificate和其他一些,这是我有权访问的

  • 我的应用程序将拥有专用的用户帐户 - 不使用Windows身份验证等 - 所以更像是用户名/密码系统,而无需输入用户名或密码

  • 服务器进行身份验证他们访问服务器通过使用某种形式的Windows验证他们的智能卡证书的,但我不能,我必须接受装入请求集合证书

  • 用户表存储在SQL Server中(现在......)

  • 不希望使用EntityFramework,因为所有应用程序数据都来自Oracle数据库并且试图获得批准将身份验证/授权表移入其中并消除两个数据库的工作,并且EF for Oracle在我们的环境中不起作用,所以我' m使用OleDb代替:(

实施这样的计划的最佳方法是什么?我开始做的是构建三个表 - Users,Roles和UserRoles - 而Users表包含(string)ClientCertificate的副本.进入的用户将通过拉取Request.ClientCertificate并查找匹配的用户记录,然后从UserRoles获取角色列表来对应用程序进行身份验证.用户对象将存储在包含用户和角色信息的会话中,并且属性将在控制器上用于通过要求某些角色来控制访问.

(我们有另一个使用这种基本方法的应用程序,但它是Linux上的J2EE所以我不能只重用它的代码)

但是,我也开始阅读有关IIdentity和IPrincipal的内容,但我不清楚这是否是我可以使用的东西.显然,我更喜欢使用由专家设计的安全模型.那么我应该使用继承自IIdentity和IPrincipal的自定义类来构建我的身份验证系统吗?或者我应该使用其他方法吗?

完全有可能像SimpleMembership这样的东西可以定制,以满足我的需求,但如果是这样,我不知道它.

感谢您的建议,非常感谢.

Sam*_*ari 5

您也可以将Microsoft的Identity用于此类高级方案.身份如此模块化,您可以将任何数据存储用于您想要的任何架构.身份验证的密码不是必须的,您可以实现自己的方案.考虑这个简单的例子:

// imaging this action is called after user authorized by remote server
public ActionResoult Login()
{
    // imaging this method gets authorized certificate string 
    // from Request.ClientCertificate or even a remote server
    var userCer=_certificateManager.GetCertificateString();

    // you have own user manager which returns user by certificate string
    var user=_myUserManager.GetUserByCertificate(userCer);

    if(user!=null)         
    {
        // user is valid, going to authenticate user for my App
        var ident = new ClaimsIdentity(
            new[] 
            {
                // since userCer is unique for each user we could easily
                // use it as a claim. If not use user table ID 
                new Claim("Certificate", userCer),

                // adding following 2 claim just for supporting default antiforgery provider
                new Claim(ClaimTypes.NameIdentifier, userCer),
                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, user.Name),

                // populate assigned user's role form your DB 
                // and add each one as a claim  
                new Claim(ClaimTypes.Role, user.Roles[0].Name),
                new Claim(ClaimTypes.Role, user.Roles[1].Name),
                // and so on
            },
            DefaultAuthenticationTypes.ApplicationCookie);

        // Identity is sign in user based on claim don't matter 
        // how you generated it Identity take care of it
        HttpContext.GetOwinContext().Authentication.SignIn(
            new AuthenticationProperties { IsPersistent = false }, ident);

        // auth is succeed, without needing any password just claim based 
        return RedirectToAction("MyAction"); 
    }
    // invalid certificate  
    ModelState.AddModelError("", "We could not authorize you :(");
    return View();
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我们授权用户和填充的角色,而不依赖于用户名,密码和任何数据存储,因为我们使用了自己的用户管理器.

一些用法示例:

[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
}
Run Code Online (Sandbox Code Playgroud)

这是一个简单的示例,您也可以实现自定义方案扩展IIdenity.阅读就像我的其他类似的答案,更多的例子,看你如何能做到几乎一切Claims.

您也可以浏览和下载基于令牌的身份验证样本仓库作为一个简单的工作示例.