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 ConsoleApp4
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
26 .UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=AuthorizationDemo;Trusted_Connection=True;MultipleActiveResultSets=true")
27 )
28 .AddRouting()
29 .AddAuthorization(options => { //授权全局注册
30 var requirement = new RolesAuthorizationRequirement(new [] { "ADMIN" }); //角色授权要求对象
31 var policy = new AuthorizationPolicy(new IAuthorizationRequirement[] { requirement }, new string[0]); //授权策略,第二个是授权方案名称
32 options.AddPolicy("HomePage", policy); //随便起个名字
33 })
34 .AddAuthentication(options => options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme).AddCookie())
35 .Configure(app => app
36 .UseAuthentication()
37 .UseRouting()
38 .UseEndpoints(endpoints =>
39 {
40 endpoints.Map("/", RenderHomePageAsync);
41 endpoints.Map("Account/Login", SignInAsync);
42 endpoints.Map("Account/Logout", SignOutAsync);
43 endpoints.Map("Account/AccessDenied", DenyAccessAsync);
44 })))
45 .Build()
46 .Run();
47 }
48
49 public static async Task RenderHomePageAsync(HttpContext context)
50 {
51 if (context?.User?.Identity?.IsAuthenticated == true)
52 {
53 var authorizationService = context.RequestServices.GetRequiredService<IAuthorizationService>(); //获取授权服务
54 var result = await authorizationService.AuthorizeAsync(context.User, "HomePage"); //传递策略,在mvc中修改为特性
55 if (result.Succeeded)
56 {
57 await context.Response.WriteAsync(
58 @"<html>
59 <head><title>Index</title></head>
60 <body>" +
61 $"<h3>{context.User.Identity.Name}, you are authorized.</h3>" +
62 @"<a href='Account/Logout'>Sign Out</a>
63 </body>
64 </html>");
65 }
66 else
67 {
68 await context.ForbidAsync();
69 }
70 }
71 else
72 {
73 await context.ChallengeAsync();
74 }
75 }
76
77 public static async Task SignInAsync(HttpContext context)
78 {
79 if (string.Compare(context.Request.Method, "GET") == 0)
80 {
81 await RenderLoginPageAsync(context, null, null, null);
82 }
83 else
84 {
85 string userName = context.Request.Form["username"];
86 string password = context.Request.Form["password"];
87 var dbContext = context.RequestServices.GetRequiredService<UserDbContext>();
88 var user = await dbContext.Users.Include(it => it.Roles).SingleOrDefaultAsync(it => it.UserName == userName.ToUpper());
89 if (user?.Password == password)
90 {
91 var identity = new GenericIdentity(userName, CookieAuthenticationDefaults.AuthenticationScheme);
92 foreach (var role in user.Roles)
93 {
94 identity.AddClaim(new Claim(ClaimTypes.Role, role.NormalizedRoleName));
95 }
96 var principal = new ClaimsPrincipal(identity);
97 await context.SignInAsync(principal);
98 }
99 else
100 {
101 await RenderLoginPageAsync(context, userName, password, "Invalid user name or password!");
102 }
103 }
104 }
105
106 private static Task RenderLoginPageAsync(HttpContext context, string userName, string password, string errorMessage)
107 {
108 context.Response.ContentType = "text/html";
109 return context.Response.WriteAsync(
110 @"<html>
111 <head><title>Login</title></head>
112 <body>
113 <form method='post'>" +
114 $"<input type='text' name='username' placeholder='User name' value = '{userName}' /> " +
115 $"<input type='password' name='password' placeholder='Password' value = '{password}' /> " +
116 @"<input type='submit' value='Sign In' />
117 </form>" +
118 $"<p style='color:red'>{errorMessage}</p>" +
119 @"</body>
120 </html>");
121 }
122
123 public static async Task SignOutAsync(HttpContext context)
124 {
125 await context.SignOutAsync();
126 await context.ChallengeAsync(new AuthenticationProperties { RedirectUri = "/" });
127 }
128
129 public static Task DenyAccessAsync(HttpContext context)
130 {
131 return context.Response.WriteAsync(
132 @"<html>
133 <head><title>Index</title></head>
134 <body>" +
135 $"<h3>{context.User.Identity.Name}, your access is denied.</h3>" +
136 @"<a href='/Account/Logout'>Sign Out</a>
137 </body>
138 </html>");
139 }
140
141
142 }
143 }