我的网站的图片不想被公开浏览、下载、盗链怎么办?本文主要通过解读一下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 : 十四.静态文件与访问授权、防盗链的更多相关文章

  1. 15.ASP.NET Core 应用程序中的静态文件中间件

    在这篇文章中,我将向大家介绍,如何使用中间件组件来处理静态文件.这篇文章中,我们讨论下面几个问题: 在ASP.NET Core中,我们需要把静态文件存放在哪里? 在ASP.NET Core中 wwwr ...

  2. centos LAMP第二部分apache配置 下载discuz!配置第一个虚拟主机 安装Discuz! 用户认证 配置域名跳转 配置apache的访问日志 配置静态文件缓存 配置防盗链 访问控制 apache rewrite 配置开机启动apache tcpdump 第二十节课

    centos    LAMP第二部分apache配置  下载discuz!配置第一个虚拟主机 安装Discuz! 用户认证 配置域名跳转  配置apache的访问日志  配置静态文件缓存  配置防盗链 ...

  3. asp.net core 教程(七)-异常处理、静态文件

    Asp.Net Core-异常处理 Asp.Net Core-异常处理 在这一章,我们将讨论异常和错误处理.当 ASP.NET Core应用程序中发生错误时,您可以以各种不同的方式来处理.让我们来看看 ...

  4. [小技巧]ASP.NET Core中如何预压缩静态文件

    原文地址:Pre-compressed static files with ASP.NET Core 作者:Gunnar Peipman 译者:Lamond Lu 译文:https://www.cnb ...

  5. Asp .Net core 2 学习笔记(3) —— 静态文件

    这个系列的初衷是便于自己总结与回顾,把笔记本上面的东西转移到这里,态度不由得谨慎许多,下面是我参考的资源: ASP.NET Core 中文文档目录 官方文档 记在这里的东西我会不断的完善丰满,对于文章 ...

  6. ASP.NET Core 1.0基础之静态文件处理

    来源 这些HTML , CSS files, image files, 和JavaScript这些静态文件,是ASP.NET能够直接响应给客户端的.本文详述下ASP.NET和静态文件的关系. Serv ...

  7. ASP.NET Core 2.2 十九. 你扔过来个json,我怎么接

    原文:ASP.NET Core 2.2 十九. 你扔过来个json,我怎么接 前文说道了Action的激活,这里有个关键的操作就是Action参数的映射与模型绑定,这里即涉及到简单的string.in ...

  8. 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的路由方案,与原来的方案在使用上差别不 ...

  9. 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 ...

随机推荐

  1. Linux 桌面玩家指南:18. 使用 Docker 隔离自己的开发环境和部署环境

    特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用$标记数学公式的开始和结束.如果某条评论中出现了两个$,MathJax 会将两个$之 ...

  2. mac电脑 上强大的RAW图像处理工具 ——RAW Power

    苹果电脑曾经有一款名为Aperture的照片处理应用,最终因为苹果软件策略的更好与升级,这款应用已经被苹果砍掉.但Aperture的开发者们并未放弃这款应用,在Mac OS上推出了一款名为RAW Po ...

  3. qml demo分析(maroon-小游戏)

    1.效果展示 这篇文章我还是分析一个qt源码中的qml程序,程序运行效果如下图所示. 图1  游戏开始 图2  游戏中 2.源码分析 这个游戏的源码文件比较多,为了能更清楚的了解整个代码,我先整体分析 ...

  4. KnockoutJS-绑定元素

    工作变更,又走回了WPF,一个来月没有接触web开发了,之前的KnockoutJS却不想放弃,继续进行知识的巩固,下个月开始重新走回web开发之路,还是得用回一些习惯了的工具.本次开始接触各绑定元素功 ...

  5. 深入解读MySQL8.0 新特性 :Crash Safe DDL

    前言 在MySQL8.0之前的版本中,由于架构的原因,mysql在server层使用统一的frm文件来存储表元数据信息,这个信息能够被不同的存储引擎识别.而实际上innodb本身也存储有元数据信息.这 ...

  6. 4.2WebHost配置「深入浅出ASP.NET Core系列」

    希望给你3-5分钟的碎片化学习,可能是坐地铁.等公交,积少成多,水滴石穿,谢谢关注. WebHost配置 覆盖配置文件和修改启动URL 覆盖配置文件和修改启动URL是经常使用的地方,覆盖配置文件可以自 ...

  7. 三种方法为QLineEdit添加清除内容按钮

    很多时候我们会发现输入的一长串内容不得不全部删除重新输入,这时比起一直按着退格键不放一个清除内容按钮更受欢迎. 今天我将介绍三种为QLineEdit添加清除内容按钮的方法,其中两种方法有较强的功能针对 ...

  8. .NET Framework框架介绍

    1.内容 .net framework c#和.net关系 掌握C#中命名空间2..net 就是微软提供的一个开发平台 版本: vs2008 3.5 vs2010 4.0 vs2012 2013 20 ...

  9. footer固定在页面底部的实现方法总结

    方法一:footer高度固定+绝对定位 HTML代码: <body> <header>头部</header> <main>中间内容</main&g ...

  10. Ueditor图片上传功能的配置

    之前的项目中碰到过图片上传功能的配置问题,但是没有记录下来,今天有个朋友突然又问到了我这个问题,当时没想起来之前怎么解决的,后来看了Ueditor的官方文档才回想起来. 官网文档巨多,一般大家遇到问题 ...