//接口
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace xingsuan.Middlewares
{
public interface IHelloFileProvider
{
public Task Invoke(HttpContext context);
public Task Invoke_AloneFile(HttpContext context);
}
}
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.FileProviders;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//读取本地文件夹下的目录 2021/3/11
namespace xingsuan.Middlewares
{
public class HelloFileProviderMiddleware:IHelloFileProvider
{
// private readonly RequestDelegate _next;
private readonly IFileProvider _fileProvider;
//public HelloFileProviderMiddleware(RequestDelegate next, IFileProvider fileProvider)
public HelloFileProviderMiddleware(IFileProvider fileProvider)
{
// _next = next;
_fileProvider = fileProvider;
}
/// <summary>
/// 获取目录下的文件名
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public async Task Invoke(HttpContext context)
{
var output = new StringBuilder("");
IDirectoryContents dir = _fileProvider.GetDirectoryContents("");//""代表根目录 获取根目录下的文件名
foreach (IFileInfo item in dir)//遍历
{
output.AppendLine(item.Name);//拼接 加回车
}
await context.Response.WriteAsync(output.ToString());//打印
}
/// <summary>
/// 读取文件内容
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public async Task Invoke_AloneFile(HttpContext context)
{
IFileInfo file = _fileProvider.GetFileInfo("~/../File/鬼谷八荒攻略.txt");
using var stream = file.CreateReadStream();
using var reader = new StreamReader(stream);
var output = await reader.ReadToEndAsync();
await context.Response.WriteAsync(output.ToString());
}
}
/// <summary>
///定义一个机制去修改用户的管道需求 this IApplicationBuilder app这种写法代表是对 IApplicationBuilder app的扩展
///在startUp中添加服务 app.UseHelloFileProvider();//添加文件中间件服务 后会导致路由失效 直接执行该函数所定义的内容
/// </summary>
public static class UseHelloFileProviderExtensions
{
public static IApplicationBuilder UseHelloFileProvider(this IApplicationBuilder app)
{
return app.UseMiddleware<HelloFileProviderMiddleware>();
}
}
}
//startup类
using Microsoft.AspNetCore.Authentication.QQ;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using StudentManagement.Data;
using StudentManagement.Middlewares;
using StudentManagement.Models;
using StudentManagement.Security;
using StudentManagement.Security.CustomTokenProvider;
using System;
using System.IO;
using xingsuan.Middlewares;
namespace StudentManagement
{
public class Startup
{
private readonly IConfiguration _configuration;
public Startup(IConfiguration configuration)
{
_configuration = configuration;
}
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
/*多语言国际化自定义资源文件*/
//services.AddMvc().AddViewLocalization(Microsoft.AspNetCore.Mvc.Razor.LanguageViewLocationExpanderFormat.Suffix,
// opt => { opt.ResourcesPath = "Resources"; });
//注入HttpContextAccessor
services.AddHttpContextAccessor();
services.AddDbContextPool<AppDbContext>(
options => options.UseSqlServer(_configuration.GetConnectionString("XingsuanConnection"))
);
services.Configure<IdentityOptions>(options =>
{
options.Password.RequiredLength = 6;
// options.Password.RequiredUniqueChars = 3;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
options.SignIn.RequireConfirmedEmail = true;
//通过自定义的CustomEmailConfirmation名称来覆盖旧有token名称,
//是它与AddTokenProvider<CustomEmailConfirmationTokenProvider<ApplicationUser>>("ltmEmailConfirmation")
//关联在一起
options.Tokens.EmailConfirmationTokenProvider = "ltmEmailConfirmation";
//指 在帐户被锁定之前允许的失败登录的次数。默认值为 5。
options.Lockout.MaxFailedAccessAttempts = 5;
//默认锁定时间为 15 分钟。
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15);
});
/// 修改所有令牌类型的有效时间为10个小时
services.Configure<DataProtectionTokenProviderOptions>(
opt =>
{
opt.TokenLifespan = TimeSpan.FromHours(10);
}
);
// 仅更改电子邮件验证令牌类型的有效时间为10秒
services.Configure<CustomEmailConfirmationTokenProviderOptions>(opt =>
{
opt.TokenLifespan = TimeSpan.FromHours(10);
}
);
services.ConfigureApplicationCookie(options =>
{
//修改拒绝访问的路由地址
options.AccessDeniedPath = new PathString("/Admin/AccessDenied");
//修改登录地址的路由
// options.LoginPath = new PathString("/Admin/Login");
//修改注销地址的路由
// options.LogoutPath = new PathString("/Admin/LogOut");
//统一系统全局的Cookie名称
options.Cookie.Name = "MockSchoolCookieName";
// 登录用户Cookie的有效期
options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
//是否对Cookie启用滑动过期时间。
options.SlidingExpiration = true;
});
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddErrorDescriber<CustomIdentityErrorDescriber>()
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders()
.AddTokenProvider<CustomEmailConfirmationTokenProvider<ApplicationUser>>("ltmEmailConfirmation");
// 策略结合声明授权
services.AddAuthorization(options =>
{
options.AddPolicy("DeleteRolePolicy", policy => policy.RequireClaim("Delete Role"));
options.AddPolicy("AdminRolePolicy", policy => policy.RequireRole("Admin"));
//策略结合多个角色进行授权
options.AddPolicy("SuperAdminPolicy", policy => policy.RequireRole("Admin", "User"));
// options.AddPolicy("EditRolePolicy", policy => policy.RequireClaim("Edit Role","true"));
// options.AddPolicy("AllowedCountryPolicy", policy => policy.RequireClaim("Country","China","USA","UK"));
//options.AddPolicy("EditRolePolicy", policy => policy.RequireAssertion( context => AuthorizeAccess(context)));
options.AddPolicy("EditRolePolicy", policy => policy.AddRequirements(new ManageAdminRolesAndClaimsRequirement()));
options.InvokeHandlersAfterFailure = false;
});
//添加授权登录需要安装授权Nuget包
services.AddAuthentication().AddMicrosoftAccount(opt =>
{
opt.ClientId = _configuration["Authentication:Microsoft:ClientId"];
opt.ClientSecret = _configuration["Authentication:Microsoft:ClientSecret"];
}).AddGitHub(options =>
{
options.ClientId = _configuration["Authentication:Github:ClientId"];
options.ClientSecret = _configuration["Authentication:Github:ClientSecret"];
});
//.AddQQ(QQOptions=>
//{
// QQOptions.AppId = _configuration["Authentication:QQ:AppId"];//qq互联申请的appid
// QQOptions.AppKey = _configuration["Authentication:QQ:Appkey"];//qq互联申请的appkey
// QQOptions.CallbackPath = "/home/index";//qq互联回调地址
// });
services.AddControllersWithViews(config =>
{
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
config.Filters.Add(new AuthorizeFilter(policy));
}).AddXmlSerializerFormatters();
services.AddScoped<IStudentRepository, SQLStudentRepository>();//为接口绑定实例 为依赖注入做准备
services.AddTransient<IHelloFileProvider, HelloFileProviderMiddleware>();//为接口绑定实例 为依赖注入做准备
services.AddSingleton<IAuthorizationHandler, CanEditOnlyOtherAdminRolesAndClaimsHandler>();
services.AddSingleton<IAuthorizationHandler, SuperAdminHandler>();
services.AddSingleton<DataProtectionPurposeStrings>();
//添加访问本地文件所需服务
services.AddSingleton<IFileProvider>(new PhysicalFileProvider(Directory.GetCurrentDirectory()));
}
// This method gets called by the runtim0e. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//如果环境是 Development,调用 Developer Exception Page
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");//拦截我们的异常
app.UseStatusCodePagesWithReExecute("/Error/{0}"); //拦截404找不到的页面信息
}
//app.UseHelloFileProvider();//添加文件中间件服务,是自定义的管道
app.UseStaticFiles();
//身份认证中间件
app.UseAuthentication();
app.UseRouting();
//身份认证(authentication)和授权(authorization)
app.UseAuthorization();
//用户数据初始化
app.UseDataInitializer();
// UseEndpoints 是一个可以处理跨不同中间件系统(如MVC、 Razor Pages、 Blazor、 SignalR和gRPC) 的路由系统。通过终结点路由可以使端点相互协作,并使系统比没有相互对话的终端中间件更全面。当然本书暂时不会涉及Razor Pages、 Blazor、 SignalR和gRPC,但是为了项目的长远规划,dotnet开发团队推荐使用终结点路由。
app.UseEndpoints(routes =>
{
routes.MapControllerRoute("default",
//正式路径
//pattern: "{controller=Home}/{action=Index}/{id?}");
//测试用路径
//pattern: "{controller=HelloFileProvider}/{action=Index}");
pattern: "{controller=HelloFileProvider}/{action=Index_wholeFile}");
});
}
//授权访问
private bool AuthorizeAccess(AuthorizationHandlerContext context)
{
return context.User.IsInRole("Admin") &&
context.User.HasClaim(claim => claim.Type == "Edit Role" && claim.Value == "true") ||
context.User.IsInRole("Super Admin");
}
}
}
对静态文件读写记得添加、
//添加访问本地文件所需服务
services.AddSingleton<IFileProvider>(new PhysicalFileProvider(Directory.GetCurrentDirectory()));
以及别忘了静态文件管道
app.UseStaticFiles();
因篇幅问题不能全部显示,请点此查看更多更全内容