概述 Commond-Line ASP.NET結構文件 Startup 配置文件 中間件和依賴註入 依賴註入原理 框架自帶的依賴註入(IServiceCollection) 依賴註入生命周期 依賴註入使用方式 通過構造函數 MVC的ActionAction中可以使用 [FromServices]來註 ...
概述
Commond-Line
ASP.NET結構文件
Startup
配置文件
中間件和依賴註入
依賴註入原理
框架自帶的依賴註入(IServiceCollection)
依賴註入生命周期
依賴註入使用方式
- 通過構造函數
- MVC的ActionAction中可以使用 [FromServices]來註入對象、
中間件(MiddleWare)
Use:進入中間件http管道模式,
Map:映射分支 Run:
執行,並返回Response
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseMyMiddleware(); } public class MyMiddleware { private readonly RequestDelegate _next; public MyMiddleware(RequestDelegate next) { _next = next; } public Task Invoke(HttpContext context) { //這裡是獲取context信息後處理的代碼 return this._next(context); } } public static class MyMiddlewareExtensions { public static IApplicationBuilder UseMyMiddleware( this IApplicationBuilder builder) { return builder.UseMiddleware<MyMiddlewareMiddleware>(); } }
中間件的執行要註意順序,因為可以終止http管道的執行
框架自帶中間件
ORM
Entity Framework Core
官方地址:https://docs.microsoft.com/zh-cn/ef/core/
services.AddDbContext<SchoolContext>(options =>options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
Entity Framework Core-Code First
//程式包管理控制項台 Install-Package Microsoft.EntityFrameworkCore.SqlServer Install-Package Microsoft.EntityFrameworkCore.Tools Install-Package Microsoft.VisualStudio.Web.CodeGeneration.Design
從資料庫生成模型
Scaffold-DbContext "Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models
併發控制
//特性方式 public class Person { public int PersonId { get; set; } [ConcurrencyCheck] public string LastName { get; set; } public string FirstName { get; set; } } //特性API方式 class MyContext : DbContext { public DbSet<Person> People { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Person>() .Property(p => p.LastName) .IsConcurrencyToken(); } } public class Person { public int PersonId { get; set; } public string LastName { get; set; } public string FirstName { get; set; } } //特性時間戳 public class Blog { public int BlogId { get; set; } public string Url { get; set; } [Timestamp] public byte[] Timestamp { get; set; } }
//時間戳 class MyContext : DbContext { public DbSet<Blog> Blogs { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Blog>() .Property(p => p.Timestamp) .IsRowVersion(); } } public class Blog { public int BlogId { get; set; } public string Url { get; set; } public byte[] Timestamp { get; set; } }
Dapper
官方地址:https://github.com/StackExchange/Dapper
許可權驗證
概念
Authentication:認證,通過自定義或三方的方式,確定用戶有效性,並分配用戶一定身份
Authorization:授權,決定用戶可以做什麼,可以帶上角色或策略來授權,並且是能過Controller或Action上的特性Authorize來授權的。
驗證方式
ConfigureServices中
//註入驗證 2.0 services.AddAuthentication(options => { options.DefaultChallengeScheme = "MyCookieAuthenticationScheme"; options.DefaultSignInScheme = "MyCookieAuthenticationScheme"; options.DefaultAuthenticateScheme = "MyCookieAuthenticationScheme"; }) .AddCookie("MyCookieAuthenticationScheme", opt => { opt.LoginPath = new PathString("/login"); opt.AccessDeniedPath = new PathString("/login"); opt.LogoutPath = new PathString("/login"); opt.Cookie.Path = "/"; });
Configure中
app.UseAuthentication();
登錄驗證
public class UserTestController : Controller { [HttpGet("users")] [Authorize(Roles = "admin,system")] public IActionResult Index() { return View(); } [HttpGet("login")] public IActionResult Login(string returnUrl) { //1、如果登錄用戶已經Authenticated,提示請勿重覆登錄 if (HttpContext.User.Identity.IsAuthenticated) { return View("Error", new string[] { "您已經登錄!" }); }else//記錄轉入地址 { ViewBag.returnUrl = returnUrl; return View();} }
[AllowAnonymous] [HttpPost("login")] public IActionResult Login(string username, string returnUrl) { //2、登錄後設置驗證 if (username == "gsw") { var claims = new Claim[]{ new Claim(ClaimTypes.Role, "admin"), new Claim(ClaimTypes.Name,"桂素偉") }; HttpContext.SignInAsync("MyCookieAuthenticationScheme",new ClaimsPrincipal(new ClaimsIdentity(claims, "Cookie"))); //給User賦值 var claPris = new ClaimsPrincipal(); claPris.AddIdentity(new ClaimsIdentity(claims)); HttpContext.User = claPris; return new RedirectResult(returnUrl == null ? "users" : returnUrl); } else { return View(); } }
UI訪問
//3、UI上訪問驗證信息 @if (User.IsInRole("abc")) { <p>你好: @User.Identity.Name</p> <a href="更高許可權">更高許可權</a> }
許可權中間件
/// <summary> /// 許可權中間件 /// </summary> public class PermissionMiddleware { /// <summary> /// 管道代理對象 /// </summary> private readonly RequestDelegate _next; /// <summary> /// 許可權中間件構造 /// </summary> /// <param name="next">管道代理對象</param> /// <param name="permissionResitory">許可權倉儲對象</param> /// <param name="option">許可權中間件配置選項</param> public PermissionMiddleware(RequestDelegate next) { _next = next; } /// <summary> /// 調用管道 /// </summary> /// <param name="context"></param> /// <returns></returns> public Task Invoke(HttpContext context) { return this._next(context); } }
自定義策略
/// <summary> /// 許可權授權Handler /// </summary> public class PermissionHandler : AuthorizationHandler<PermissionRequirement> { /// <summary> /// 用戶許可權 /// </summary> public List<Permission> Permissions { get; set; } protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) { //賦值用戶許可權 Permissions = requirement.Permissions; //從AuthorizationHandlerContext轉成HttpContext,以便取出表求信息 var httpContext = (context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext).HttpContext; //請求Url var questUrl = httpContext.Request.Path.Value.ToLower(); //是否經過驗證 var isAuthenticated = httpContext.User.Identity.IsAuthenticated; if (isAuthenticated) { //許可權中是否存在請求的url if (Permissions.GroupBy(g => g.Url).Where(w => w.Key.ToLower() == questUrl).Count() > 0) { var name = httpContext.User.Claims.SingleOrDefault(s => s.Type == requirement.ClaimType).Value; //驗證許可權 if (Permissions.Where(w => w.Name == name && w.Url.ToLower() == questUrl).Count() > 0) { context.Succeed(requirement); } else { //無許可權跳轉到拒絕頁面 httpContext.Response.Redirect(requirement.DeniedAction); } } else { context.Succeed(requirement); } } return Task.CompletedTask; } }
自定義策略-JWT
/// <summary> /// 許可權授權Handler /// </summary> public class PermissionHandler : AuthorizationHandler<PermissionRequirement> { /// <summary> /// 驗證方案提供對象 /// </summary> public IAuthenticationSchemeProvider Schemes { get; set; } /// <summary> /// 自定義策略參數 /// </summary> public PermissionRequirement Requirement { get; set; } /// <summary> /// 構造 /// </summary> /// <param name="schemes"></param> public PermissionHandler(IAuthenticationSchemeProvider schemes) { Schemes = schemes; } protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) { ////賦值用戶許可權 Requirement = requirement; //從AuthorizationHandlerContext轉成HttpContext,以便取出表求信息 var httpContext = (context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext).HttpContext; //請求Url var questUrl = httpContext.Request.Path.Value.ToLower(); //判斷請求是否停止 var handlers = httpContext.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>(); foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync()) { var handler = await handlers.GetHandlerAsync(httpContext, scheme.Name) as IAuthenticationRequestHandler; if (handler != null && await handler.HandleRequestAsync()) { context.Fail(); return; } } //判斷請求是否擁有憑據,即有沒有登錄 var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync(); if (defaultAuthenticate != null) { var result = await httpContext.AuthenticateAsync(defaultAuthenticate.Name); //result?.Principal不為空即登錄成功 if (result?.Principal != null) { httpContext.User = result.Principal; //許可權中是否存在請求的url if (Requirement.Permissions.GroupBy(g => g.Url).Where(w => w.Key.ToLower() == questUrl).Count() > 0) { var name = httpContext.User.Claims.SingleOrDefault(s => s.Type == requirement.ClaimType).Value; //驗證許可權 if (Requirement.Permissions.Where(w => w.Name == name && w.Url.ToLower() == questUrl).Count() <= 0) { //無許可權跳轉到拒絕頁面 httpContext.Response.Redirect(requirement.DeniedAction); } } context.Succeed(requirement); return; } } //判斷沒有登錄時,是否訪問登錄的url,並且是Post請求,並且是form表單提交類型,否則為失敗 if (!questUrl.Equals(Requirement.LoginPath.ToLower(), StringComparison.Ordinal) && (!httpContext.Request.Method.Equals("POST") || !httpContext.Request.HasFormContentType)) { context.Fail(); return; } context.Succeed(requirement); } }