ASP.NET Core 2.1 : 十四.静态文件与访问授权、防盗链
我的网站的图片不想被公开浏览、下载、盗链怎么办?本文主要通过解读一下ASP.NET Core对于静态文件的处理方式的相关源码,来看一下为什么是wwwroot文件夹,如何修改或新增一个静态文件夹,为什么新增的文件夹名字不会被当做controller处理?访问授权怎么做?(ASP.NET Core 系列目录)
一、静态文件夹
所谓静态文件,直观的说就是wwwroot目录下的一些直接提供给访问者的文件,例如css,图片、js文件等。 当然这个wwwroot目录是默认目录,
这个是在Main->CreateDefaultBuilder的时候做了默认设置。
public static class HostingEnvironmentExtensions
{
public static void Initialize(this IHostingEnvironment hostingEnvironment, string contentRootPath, WebHostOptions options)
{
//省略部分代码
var webRoot = options.WebRoot;
if (webRoot == null)
{
// Default to /wwwroot if it exists.
var wwwroot = Path.Combine(hostingEnvironment.ContentRootPath, "wwwroot");
if (Directory.Exists(wwwroot))
{
hostingEnvironment.WebRootPath = wwwroot;
}
}
else
{
hostingEnvironment.WebRootPath = Path.Combine(hostingEnvironment.ContentRootPath, webRoot);
}
//省略部分代码
}
}
二、处理方式
前文关于中间件部分说过,在Startup文件中,有一个 app.UseStaticFiles() 方法的调用,这里是将静态文件的处理中间件作为了“处理管道”的一部分,
并且这个中间件是写在 app.UseMvc 之前, 所以当一个请求进来之后, 会先判断是否为静态文件的请求,如果是,则在此做了请求处理,这时候请求会发生短路,不会进入后面的mvc中间件处理步骤。
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
} app.UseStaticFiles(); app.UseCookiePolicy();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
三、新增静态文件目录
除了这个默认的wwwroot目录,需要新增一个目录来作为静态文件的目录,可以Startup文件的 app.UseStaticFiles() 下面继续use,例如下面代码
app.UseFileServer(new FileServerOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), "NewFilesPath")),
RequestPath = "/NewFiles"
});
含义就是指定应用程序目录中的一个名为“NewFilesPath”的文件夹,将它也设置问静态文件目录, 而这个目录的访问路径为"/NewFiles"。
例如文件夹"NewFilesPath"下面有一个test.jpg, 那么我们可以通过这样的地址来访问它:http://localhost:64237/NewFiles/test.jpg。
四、中间件的处理方式
静态文件的处理中间件为StaticFileMiddleware,主要的处理方法 Invoke 代码如下
public async Task Invoke(HttpContext context)
{
var fileContext = new StaticFileContext(context, _options, _matchUrl, _logger, _fileProvider, _contentTypeProvider); if (!fileContext.ValidateMethod())
{
_logger.LogRequestMethodNotSupported(context.Request.Method);
}
else if (!fileContext.ValidatePath())
{
_logger.LogPathMismatch(fileContext.SubPath);
}
else if (!fileContext.LookupContentType())
{
_logger.LogFileTypeNotSupported(fileContext.SubPath);
}
else if (!fileContext.LookupFileInfo())
{
_logger.LogFileNotFound(fileContext.SubPath);
}
else
{
// If we get here, we can try to serve the file
fileContext.ComprehendRequestHeaders();
switch (fileContext.GetPreconditionState())
{
case StaticFileContext.PreconditionState.Unspecified:
case StaticFileContext.PreconditionState.ShouldProcess:
if (fileContext.IsHeadMethod)
{
await fileContext.SendStatusAsync(Constants.Status200Ok);
return;
}
try
{
if (fileContext.IsRangeRequest)
{
await fileContext.SendRangeAsync();
return;
}
await fileContext.SendAsync();
_logger.LogFileServed(fileContext.SubPath, fileContext.PhysicalPath);
return;
}
catch (FileNotFoundException)
{
context.Response.Clear();
}
break;
case StaticFileContext.PreconditionState.NotModified:
_logger.LogPathNotModified(fileContext.SubPath);
await fileContext.SendStatusAsync(Constants.Status304NotModified);
return; case StaticFileContext.PreconditionState.PreconditionFailed:
_logger.LogPreconditionFailed(fileContext.SubPath);
await fileContext.SendStatusAsync(Constants.Status412PreconditionFailed);
return; default:
var exception = new NotImplementedException(fileContext.GetPreconditionState().ToString());
Debug.Fail(exception.ToString());
throw exception;
}
}
await _next(context);
}
当HttpContext进入此中间件后会尝试封装成StaticFileContext, 然后对其逐步判断,例如请求的URL是否与设置的静态目录一致, 判断文件是否存在,判断文件类型等,
若符合要求 ,会进一步判断文件是否有修改等。
五、静态文件的授权管理
默认情况下,静态文件是不需要授权,可以公开访问的。
因为即使采用了授权, app.UseAuthentication(); 一般也是写在 app.UseStaticFiles() 后面的,那么如果我们想对其进行授权管理,首先想到可以改写 StaticFileMiddleware 这个中间件,
在其中添加一些自定义的判断条件,但貌似不够友好。而且这里只能做一些大类的判断,比如请求的IP地址是否在允许范围内这样的还行,如果要根据登录用户的权限来判断(比如用户只能看到自己上传的图片)就不行了,
因为权限的判断写在这个中间件之后。所以可以通过Filter的方式来处理,首先可以在应用目录中新建一个"images"文件夹, 而这时就不要把它设置为静态文件目录了,这样这个"images"目录的文件默认情况下是不允许访问的,
然后通过Controller返回文件的方式来处理请求,如下代码所示
[Route("api/[controller]")]
[AuthorizeFilter]
public class FileController : Controller
{
[HttpGet("{name}")]
public FileResult Get(string name)
{
var file = Path.Combine(Directory.GetCurrentDirectory(), "images", name);
return PhysicalFile(file, "application/octet-stream");
}
}
在AuthorizeFilter中进行相关判断,代码如下
public class AuthorizeFilter: ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
base.OnActionExecuting(context); if (context.RouteData.Values["controller"].ToString().ToLower().Equals("file"))
{
bool isAllow = false;//在此进行一系列访问权限验证,如果失败,返回一个默认图片,例如logo或不允许访问的提示图片 if (!isAllow)
{
var file = Path.Combine(Directory.GetCurrentDirectory(), "images", "default.png"); context.Result = new PhysicalFileResult(file, "application/octet-stream"); }
}
}
}
ASP.NET Core 2.1 : 十四.静态文件与访问授权、防盗链的更多相关文章
- 15.ASP.NET Core 应用程序中的静态文件中间件
在这篇文章中,我将向大家介绍,如何使用中间件组件来处理静态文件.这篇文章中,我们讨论下面几个问题: 在ASP.NET Core中,我们需要把静态文件存放在哪里? 在ASP.NET Core中 wwwr ...
- centos LAMP第二部分apache配置 下载discuz!配置第一个虚拟主机 安装Discuz! 用户认证 配置域名跳转 配置apache的访问日志 配置静态文件缓存 配置防盗链 访问控制 apache rewrite 配置开机启动apache tcpdump 第二十节课
centos LAMP第二部分apache配置 下载discuz!配置第一个虚拟主机 安装Discuz! 用户认证 配置域名跳转 配置apache的访问日志 配置静态文件缓存 配置防盗链 ...
- asp.net core 教程(七)-异常处理、静态文件
Asp.Net Core-异常处理 Asp.Net Core-异常处理 在这一章,我们将讨论异常和错误处理.当 ASP.NET Core应用程序中发生错误时,您可以以各种不同的方式来处理.让我们来看看 ...
- [小技巧]ASP.NET Core中如何预压缩静态文件
原文地址:Pre-compressed static files with ASP.NET Core 作者:Gunnar Peipman 译者:Lamond Lu 译文:https://www.cnb ...
- Asp .Net core 2 学习笔记(3) —— 静态文件
这个系列的初衷是便于自己总结与回顾,把笔记本上面的东西转移到这里,态度不由得谨慎许多,下面是我参考的资源: ASP.NET Core 中文文档目录 官方文档 记在这里的东西我会不断的完善丰满,对于文章 ...
- ASP.NET Core 1.0基础之静态文件处理
来源 这些HTML , CSS files, image files, 和JavaScript这些静态文件,是ASP.NET能够直接响应给客户端的.本文详述下ASP.NET和静态文件的关系. Serv ...
- ASP.NET Core 2.2 十九. 你扔过来个json,我怎么接
原文:ASP.NET Core 2.2 十九. 你扔过来个json,我怎么接 前文说道了Action的激活,这里有个关键的操作就是Action参数的映射与模型绑定,这里即涉及到简单的string.in ...
- ASP.NET Core 2.2 : 十六.扒一扒新的Endpoint路由方案 try.dot.net 的正确使用姿势 .Net NPOI 根据excel模板导出excel、直接生成excel .Net NPOI 上传excel文件、提交后台获取excel里的数据
ASP.NET Core 2.2 : 十六.扒一扒新的Endpoint路由方案 ASP.NET Core 从2.2版本开始,采用了一个新的名为Endpoint的路由方案,与原来的方案在使用上差别不 ...
- ExpandoObject与DynamicObject的使用 RabbitMQ与.net core(一)安装 RabbitMQ与.net core(二)Producer与Exchange ASP.NET Core 2.1 : 十五.图解路由(2.1 or earler) .NET Core中的一个接口多种实现的依赖注入与动态选择看这篇就够了
ExpandoObject与DynamicObject的使用 using ImpromptuInterface; using System; using System.Dynamic; names ...
随机推荐
- 关于微信企业付款到零钱X509Certificate2读取证书信息,发布到服务器访问不到的解决方案
前言: 最近做了一个通过调用微信企业付款到用户零钱的功能,真的挺奇怪的,在我本地调试的时候都没有问题,但是当我发布到服务上的时候却一直无法读取到我的证书信息.读取的代码如下,使用的是微信官方文档提供 ...
- 【Python实践-2】求一个或多个数的乘积
# -*- coding: utf-8 -*- #定义一个函数,可接收一个或多个数并计算乘积 def product(*numbers): s=1 for n in numbers: s=s*n re ...
- 7. VIM 系列 - 程序员利器(语法检测、代码块补全、symbol管理、函数跳转)
目录 1. 语法检查利器 ale 2. 补全代码块 3. symbol 管理器 taglist.vim 4. 函数跳转 1. 语法检查利器 ale 安装 ale Plug 'w0rp/ale' 配置 ...
- kubernetes 存储卷
kubernetes 存储卷 数据卷用于实现容器持久化数据,Kubernetes对于数据卷重新定义,提供了丰富强大的功能.在Kubernetes系统中,当Pod重建的时候,数据卷会丢失,Kube ...
- qt捕获全局windows消息
qt 如何捕获全屏的鼠标事件,这个帖子上面主要讲述了下嵌入式qt怎么抓取系统级消息,不过从这篇文章中我也看到了希望,有个回复说winEventFilter支持这种方式,然后我就顺着这个线索找到了na ...
- LongLightUtils【保持屏幕常亮工具类】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 这里只是简单记录下保持屏幕常亮工具类LongLightUtils的使用,具体请阅读参考资料<Android屏幕常亮,其实很简单 ...
- .NET Core中的一个接口多种实现的依赖注入与动态选择看这篇就够了
最近有个需求就是一个抽象仓储层接口方法需要SqlServer以及Oracle两种实现方式,为了灵活我在依赖注入的时候把这两种实现都给注入进了依赖注入容器中,但是在服务调用的时候总是获取到最后注入的那个 ...
- Dalvik 虚拟机操作码
Dalvik 虚拟机操作码 表中的vx.vy.vz表示某个Dalvik寄存器.根据不同指令可以访问16.256或64K寄存器. 表中lit4.lit8.lit16.lit32.lit64表示字面值(直 ...
- 【我们一起写框架】MVVM的WPF框架(四)—DataGrid
前言 这个框架写到这里,应该有很多同学发现,框架很多地方的细节,其实是违背了MVVM的设计逻辑的. 没错,它的确是违背了. 但为什么明知道违背设计逻辑,还要这样编写框架呢? 那是因为,我们编写的是框架 ...
- void类型和void* 的用法
C语言中的void 和 void * 总结 1.void的作用 c语言中,void为“不确定类型”,不可以用void来声明变量.如:void a = 10:如果出现这样语句编译器会报错:variab ...