身份、权限、用户

发布时间 2023-07-29 23:25:46作者: 张志恒的博客

iidentity            身份

claim                身份信息

claimPrincipal    有多个身份,但有一个主身份  claims 所有身份,表示用户。。一个用户有多个身份,每个身份里面有多个信息

采用基于票据的认证!

AuthenticationTicket 票据,对claimPrincipal的封装。包括claimPrincipal 和认证方式 ,还有过期时间等等。

授权==设置一个策略,就是用户携带的证明与策略是否匹配,没有具体规定,用来判断,最常用角色

将用户添加到一个角色,就是把权限给某个用户。

代码:

using System.Collections.Generic;

namespace ConsoleApp3.Models
{
    public class Role
    {
        public string RoleName { get; set; }
        public string NormalizedRoleName { get; set; }
        public virtual ICollection<UserRole> Users { get; } = new List<UserRole>();

        public Role() { }
        public Role(string roleName)
        {
            RoleName = roleName;
            NormalizedRoleName = roleName.ToUpper();
        }
    }

}
Role
using System.Collections.Generic;

namespace ConsoleApp3.Models
{
    public class User
    {
        public string UserName { get; set; }
        public string NormalizedUserName { get; set; }
        public string Password { get; set; }
        public virtual ICollection<UserRole> Roles { get; } = new List<UserRole>();

        public User() { }
        public User(string userName, string password)
        {
            UserName = userName;
            NormalizedUserName = userName.ToUpper();
            Password = password;
        }
    }

}
User
namespace ConsoleApp3.Models
{
    public class UserRole
    {
        public string NormalizedUserName { get; set; }
        public string NormalizedRoleName { get; set; }
    }
}
UserRole
 1 using ConsoleApp3.Models;
 2 using Microsoft.EntityFrameworkCore;
 3 
 4 namespace ConsoleApp3
 5 {
 6     public sealed class UserDbContext : DbContext
 7     {
 8         public DbSet<User> Users { get; set; }
 9         public DbSet<Role> Roles { get; set; }
10         public DbSet<UserRole> UserRoles { get; set; }
11 
12         protected override void OnModelCreating(ModelBuilder modelBuilder)
13         {
14             modelBuilder.Entity<User>(builder =>
15             {
16                 builder.HasKey(user => user.NormalizedUserName);
17                 builder.HasMany(user => user.Roles).WithOne().HasForeignKey(
18                     userRole => userRole.NormalizedUserName);
19             });
20             modelBuilder.Entity<Role>(builder =>
21             {
22                 builder.HasKey(role => role.NormalizedRoleName);
23                 builder.HasMany(role => role.Users).WithOne().HasForeignKey(
24                     userRole => userRole.NormalizedRoleName);
25             });
26             modelBuilder.Entity<UserRole>(builder => builder.HasKey(
27                 userRole => new { userRole.NormalizedUserName, userRole.NormalizedRoleName }));
28         }
29         public UserDbContext(DbContextOptions options) : base(options)
30         {
31             Database.EnsureCreated();
32             if (Users.Find("User1") != null) return;
33 
34             Users.Add(new User("User1", "123"));
35             Users.Add(new User("User2", "123"));
36             Roles.Add(new Role("Admin"));
37             UserRoles.Add(new UserRole
38             {
39                 NormalizedUserName = "USER1",
40                 NormalizedRoleName = "ADMIN"
41             });
42             SaveChanges();
43         }
44     }
45 }
DbContext
  1 using System;
  2 using System.Security.Claims;
  3 using System.Security.Principal;
  4 using System.Threading.Tasks;
  5 using Microsoft.AspNetCore.Authentication;
  6 using Microsoft.AspNetCore.Authentication.Cookies;
  7 using Microsoft.AspNetCore.Authorization;
  8 using Microsoft.AspNetCore.Authorization.Infrastructure;
  9 using Microsoft.AspNetCore.Builder;
 10 using Microsoft.AspNetCore.Hosting;
 11 using Microsoft.AspNetCore.Http;
 12 using Microsoft.EntityFrameworkCore;
 13 using Microsoft.Extensions.DependencyInjection;
 14 using Microsoft.Extensions.Hosting;
 15 
 16 namespace ConsoleApp3
 17 {
 18     class Program
 19     {
 20         static void Main(string[] args)
 21         {
 22             Host.CreateDefaultBuilder()
 23                 .ConfigureWebHostDefaults(builder => builder
 24                     .ConfigureServices(collection => collection
 25                         .AddDbContext<UserDbContext>(options => options           //注册DbContext
 26                             .UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=AuthorizationDemo;Trusted_Connection=True;MultipleActiveResultSets=true")
 27                         )
 28                         .AddRouting()
 29                         .AddAuthorization()                                        //注册认证中间件,cook验证权限
 30                         .AddAuthentication(options => options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme).AddCookie())
 31                     .Configure(app => app                                          //注册认证中间件,cook验证权限 
 32                         .UseAuthentication()
 33                         .UseRouting()
 34                         .UseEndpoints(endpoints =>                                      //节点中间件
 35                         {
 36                             endpoints.Map("/", RenderHomePageAsync);
 37                             endpoints.Map("Account/Login", SignInAsync);                  //委托和路由映射关系,没有登陆到首页
 38                             endpoints.Map("Account/Logout", SignOutAsync);                //委托和路由映射关系,登陆,默认路径
 39                             endpoints.Map("Account/AccessDenied", DenyAccessAsync);       //委托和路由映射关系,没有权限,访问拒绝
 40                         })))
 41                 .Build()
 42                 .Run();
 43         }
 44 
 45         public static async Task RenderHomePageAsync(HttpContext context)                   //主页
 46         {
 47             if (context?.User?.Identity?.IsAuthenticated == true)            //用户是否授权
 48             {
 49                 var requirement = new RolesAuthorizationRequirement(new [] { "ADMIN" });                               //授权交验  ,要求授权用户至少有一个角色  //创建角色需求要求对象,ADMIN角色
 50                 var authorizationService = context.RequestServices.GetRequiredService<IAuthorizationService>();         //从当前上下文中找到授权
 51                 var result = await authorizationService.AuthorizeAsync(context.User, null, new IAuthorizationRequirement[] { requirement });   //判断用户是有ADMIN角色,最关键步骤,对用户进行验证
 52                 if (result.Succeeded)                                                                                                          //判断是否成功
 53                 {
 54                     await context.Response.WriteAsync(
 55                         @"<html>
 56                     <head><title>Index</title></head>
 57                     <body>" +
 58                         $"<h3>{context.User.Identity.Name}, you are authorized.</h3>" +
 59                         @"<a href='Account/Logout'>Sign Out</a>
 60                     </body>
 61                 </html>");
 62                 }
 63                 else
 64                 {
 65                     await context.ForbidAsync();          //访问拒绝!
 66                 }
 67             }
 68             else
 69             {
 70                 await context.ChallengeAsync();
 71             }
 72         }
 73 
 74           public static async Task SignInAsync(HttpContext context)
 75         {
 76             if (string.Compare(context.Request.Method, "GET") == 0)
 77             {
 78                 await RenderLoginPageAsync(context, null, null, null);
 79             }
 80             else
 81             {
 82                 string userName = context.Request.Form["username"];
 83                 string password = context.Request.Form["password"];
 84                 var dbContext = context.RequestServices.GetRequiredService<UserDbContext>();
 85                 var user = await dbContext.Users.Include(it => it.Roles).SingleOrDefaultAsync(it => it.UserName == userName.ToUpper());  //数据库查找用户
 86                 if (user?.Password == password)
 87                 {
 88                     var identity = new GenericIdentity(userName, CookieAuthenticationDefaults.AuthenticationScheme);                     //经过认证的身份,名称和权限方案
 89                     foreach (var role in user.Roles)
 90                     {
 91                         identity.AddClaim(new Claim(ClaimTypes.Role, role.NormalizedRoleName));             //ClaimTypes.Role枚举类型   //权限角色类型,加入身份                           
 92                     }
 93                     var principal = new ClaimsPrincipal(identity);                                                                       //身份分配给用户
 94                     await context.SignInAsync(principal);                                                                                 //把用户信息登陆到context上下文   
 95                 }
 96                 else
 97                 {
 98                     await RenderLoginPageAsync(context, userName, password, "Invalid user name or password!");                          //密码不对
 99                 }
100             }
101         }
102 
103         private static Task RenderLoginPageAsync(HttpContext context, string userName, string password, string errorMessage)
104         {
105             context.Response.ContentType = "text/html";
106             return context.Response.WriteAsync(
107                 @"<html>
108                 <head><title>Login</title></head>
109                 <body>
110                     <form method='post'>" +
111                             $"<input type='text' name='username' placeholder='User name' value = '{userName}' /> " +
112                             $"<input type='password' name='password' placeholder='Password' value = '{password}' /> " +
113                             @"<input type='submit' value='Sign In' />
114                     </form>" +
115                             $"<p style='color:red'>{errorMessage}</p>" +
116                     @"</body>
117             </html>");
118         }
119 
120         public static async Task SignOutAsync(HttpContext context)
121         {
122             await context.SignOutAsync();                    //上下文登出
123             await context.ChallengeAsync(new AuthenticationProperties { RedirectUri = "/" });          //重新定向
124         }
125 
126         public static Task DenyAccessAsync(HttpContext context)
127         {
128             return context.Response.WriteAsync(
129                 @"<html>
130                 <head><title>Index</title></head>
131                 <body>" +
132                 $"<h3>{context.User.Identity.Name}, your access is denied.</h3>" +
133                 @"<a href='/Account/Logout'>Sign Out</a>
134                 </body>
135             </html>");
136         } 
137 
138       
139     }
140 }