回到最初的身份标识——Identity

身份标识是 .NET 安全体系中最最基础的概念,称为 Identity。在任何一个系统中,每一次对系统的访问应该都需要对其身份进行标识,例如游客。

身份的标识和主体

标识(Identity)

身份标识好比一个人的身份证,有一个唯一的标识号码,例如你的身份证号,网站的邮箱、用户名等,能表明这个用户的身份信息。

在命名空间 System.Security.Principal 中,定义了一个接口 IIdentity

//
// 摘要:
//     定义标识对象的基本功能。
public interface IIdentity
{
    //
    // 摘要:
    //     获取当前用户的名称。
    //
    // 返回结果:
    //     以其名义运行代码的用户的名称。
    string Name { get; }
    //
    // 摘要:
    //     获取使用的身份验证的类型。
    //
    // 返回结果:
    //     用于标识用户的身份验证的类型。
    string AuthenticationType { get; }
    //
    // 摘要:
    //     获取一个值,该值指示是否已验证用户。
    //
    // 返回结果:
    //     如果用户已经过验证,则为 true;否则为 false。
    bool IsAuthenticated { get; }
}
  • Name:表示身份标识的唯一名称,例如用户名
  • AuthenticationType:作为认证的一种类型,比如 Windows 认证,数字证书认证等等
  • IsAuthenticated:用于判断该用户是否通过了认证,通俗而言就是是否登录

这是最主要的一个接口,表示了身份标识的基本信息,你可以通过这个接口来扩展自己的身份标识。

身份主体(Pricipal)

可以容纳一个或多个身份标识的主体,一个系统只能有一个主体。

只能使用主体来将身份标识进行包裹,一个系统只能会有一个主体,且是线程隔离的。

 //
 // 摘要:
 //     Defines the basic functionality of a principal object.
 public interface IPrincipal
 {
     //
     // 摘要:
     //     Gets the identity of the current principal.
     //
     // 返回结果:
     //     The System.Security.Principal.IIdentity object associated with the current principal.

     IIdentity Identity { get; }

     //
     // 摘要:
     //     Determines whether the current principal belongs to the specified role.
     //
     // 参数:
     //   role:
     //     The name of the role for which to check membership.
     //
     // 返回结果:
     //     true if the current principal is a member of the specified role; otherwise, false.
     bool IsInRole(string role);
 }
  • IPrincipal 接口只有一个 IIdentity 的接口,说明主体包含了一个标识;
  • IsInRole 这个方法用于判断当前标识的角色;

内置的主体和标识

WindowsPrincipal 和 WindowsIdentity

顾名思义就是 Windows 的主体和标识。

可以通过这两个对象直接拿到当前登录到 Windows 的账号信息。

以下是示例代码:

static void Main(string[] args)
{
    var user = WindowsIdentity.GetCurrent();

    Console.WriteLine("计算机名称:{0}",user.Name);            
    Console.WriteLine("系统账户:{0}", user.IsSystem);
    Console.WriteLine("游客账户:{0}", user.IsGuest);
    Console.WriteLine("----声明----");
    foreach (var item in user.Claims)
    {
        Console.WriteLine("{0}:{1}", item.Type, item.Value);
    }
}

GenericPricipal 和 GenericIdentity

表示很广泛的主体和标识,可以自由进行应用。

var identity = new GenericIdentity("张三");
Console.WriteLine(identity.Name); //输出张三

//添加其他字段
identity.AddClaim(new Claim("email", "abcd@qq.com"));
identity.AddClaim(new Claim("mobile", "1861943821"));
identity.AddClaim(new Claim("nationality", "中国"));

ClaimPricipal 和 ClaimIdentity

基于声明的主体和标识。这是目前最广泛的使用,以上两种类型都是从这个实例派生。

你可以把声明理解成一个字典,不同字典的是Key可以重复。

基于声明的技术可以用于可以动态的创建字段。

var claimIdentity = new ClaimsIdentity();
claimIdentity.AddClaim(new Claim("username", "张三"));
claimIdentity.AddClaim(new Claim("email", "abcd@qq.com"));
claimIdentity.AddClaim(new Claim("mobile", "1861943821"));
claimIdentity.AddClaim(new Claim("nationality", "中国"));
claimIdentity.AddClaim(new Claim("role", "管理员"));
claimIdentity.AddClaim(new Claim("role", "普通用户"));

var claimPricipal = new ClaimsPrincipal(claimIdentity);
Console.WriteLine(claimPricipal.FindFirst("username"));
Console.WriteLine(claimPricipal.FindFirst("email"));
foreach (var item in claimPricipal.FindAll("role"))
{
    Console.WriteLine("{0}:{1}", item.Type, item.Value);
}

通过 FindFirstFindAll 方法查找类型(Key)的声明。

自定义主体和标识

你可以根据自己的需要自定义适合自己的主体和标识。

  • 实现 IIdentity 接口以实现自己的标识类。
  • 实现 IPrincipal 接口以实现自己的主体类。

以下是示例代码:

public class MyIdentity : IIdentity
{
    public MyIdentity(string name,string role)
    {
        Name = name;
        Role = role;
    }

    public string AuthenticationType => "自定义";
    public bool IsAuthenticated => !string.IsNullOrEmpty(Name);
    public string Name { get; }
    public string Role { get; }
}

public class MyPrincipal : IPrincipal
{
    private readonly MyIdentity _identity;
    public MyPrincipal(MyIdentity identity)
    {
        _identity = identity;
    }

    public IIdentity Identity => _identity;

    public bool IsInRole(string role)
    {
        return _identity.Role == role;
    }
}

使用方式:

var myIdentity = new MyIdentity("张三", "管理员");
var myPrincipal = new MyPrincipal(myIdentity);

Console.WriteLine("姓名:{0}",myPrincipal.Identity.Name);
Console.WriteLine("是管理员吗:{0}", myPrincipal.IsInRole("管理员"));

总结

在整个 .NET 框架中会,当你需要用到内置的用户标识时,你会看到已经被定义好了的 IPrincipal 接口或 IIdentity 接口,例如 MVC 中的 User 对象:
在这里插入图片描述
通过 User.Identity.IsAuthenticated 判断是否登录,通过 User.Identity.Name 获取用户名。

我看到很多同学都是自己定义 UserInfo 类似的对象来保存当前登录用户,比如存在 Session 或 Cookie 中。如果你能很好的理解底层原理,你可以很轻松的利用本来就设计好的用户体系,包括微软的 Identity 框架。

下一章,将手把手教你前后端分离所使用的 JWT 和 Identity 的配合。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叫我 Teacher 周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值