首页 > 解决方案 > ASP.NET Core 3.1 图像 URL 错误代码 302 重定向

问题描述

ASP.NET Core 3.1 网站托管在使用 https 的 IIS 的 Windows 服务器上。

尝试访问特定文件夹中的图像时,图像无法显示,请求重定向到登录页面。

重定向失败的图像路径示例:

https://example.com/samadhi/staff/6890.jpg

https://example.com/samadhi/staff/logo2.jpg

有效的图像路径示例:

https://example.com/samadhi/mms/qrcode15.jpg

https://example.com/samadhi/body_map.jpg

在 Plesk 控制面板中,我看到“IIS 访问”条目,如下所示:

302 GET /samadhi/staff/UserPic.jpg - HTTP/2
302 GET /samadhi/staff/318.jpg - HTTP/1.1

其他更详细的“ModSecurity”条目显示如下:

3891110101670432115 124.171.83.143 80 127.0.0.1 80
--6c3d0000-B--
GET /samadhi/staff/6890.jpg HTTP/1.1
Host: example.net.au
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; Tablet PC 2.0; Zoom 3.6.0)

--6c3d0000-F--
HTTP/1.1 500 Internal Server Error

--6c3d0000-H--
Message: Warning. Match of "pm AppleWebKit Android" against "REQUEST_HEADERS:User-Agent" required. [file "C:\/Program Files (x86)/Plesk/ModSecurity/rules/modsecurity_crs-plesk/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf"] [line "1228"] [id "920300"] [msg "Request Missing an Accept Header"] [severity "NOTICE"] [ver "OWASP_CRS/3.3.0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-protocol"] [tag "OWASP_CRS"] [tag "capec/1000/210/272"] [tag "PCI/6.5.10"] [tag "paranoia-level/2"]
Apache-Handler: IIS
Stopwatch: 1632221945009248 4997 (- - -)
Stopwatch2: 1632221945009248 4997; combined=4997, p1=4997, p2=0, p3=0, p4=0, p5=0, sr=4997, sw=0, l=0, gc=0
Producer: ModSecurity for IIS (STABLE)/2.9.3 (http://www.modsecurity.org/); OWASP_CRS/3.3.0.
Server: ModSecurity Standalone
Engine-Mode: "ENABLED"

--6c3d0000-Z--
--84670000-A--

启动.cs

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }
    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        try
        {
            services.AddRazorPages()
                .AddRazorRuntimeCompilation();

            services.AddControllersWithViews();

            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, o =>
                {
                    o.ExpireTimeSpan = new TimeSpan(90, 0, 0, 0);
                    o.AccessDeniedPath = new PathString("/Samadhi/SignIn/");
                    o.LoginPath = new PathString("/Samadhi/SignIn/");
                    o.LogoutPath = new PathString("/Samadhi/SignOut/");
                    var defaultCallback = o.Events.OnRedirectToLogin;
                    o.Events.OnRedirectToLogin = context =>
                    {
                        if (context.Request.Path.StartsWithSegments(new PathString("/samadhi"), StringComparison.OrdinalIgnoreCase))
                        {
                            context.RedirectUri = "/Samadhi/SignIn/";
                            context.Response.Redirect(context.RedirectUri);
                        }
                        else if (context.Request.Path.StartsWithSegments(new PathString("/consultant"), StringComparison.OrdinalIgnoreCase))
                        {
                            context.RedirectUri = "/Consultant/SignIn/";
                            context.Response.Redirect(context.RedirectUri);
                        }
                        else if (context.Request.Path.StartsWithSegments(new PathString("/candidate"), StringComparison.OrdinalIgnoreCase))
                        {
                            context.RedirectUri = "/Candidate/SignIn/";
                            context.Response.Redirect(context.RedirectUri);
                        }
                        return defaultCallback(context);
                    };                        
                    o.Validate();
                });

            services.AddScoped<CustomCookieAuthenticationEvents>();

            services.Configure<Microsoft.AspNetCore.Identity.IdentityOptions>(o =>
            {
                // Password settings
                o.Password.RequireDigit = true;
                o.Password.RequireLowercase = true;
                o.Password.RequireNonAlphanumeric = true;
                o.Password.RequireUppercase = true;
                o.Password.RequiredLength = 8;
                o.Password.RequiredUniqueChars = 1;

                // Lockout settings
                o.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);

                o.Lockout.MaxFailedAccessAttempts = 5;
                o.Lockout.AllowedForNewUsers = true;

                // User settings
                o.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
                o.User.RequireUniqueEmail = true;
            });

            // add detection services container and device resolver service
            services.AddDetectionCore()
                .AddDevice();

            // google recaptcha
            services.Configure<ReCAPTCHASettings>(Configuration.GetSection("GooglereCAPTCHA"))
                .AddTransient<ReCAPTCHAService>();

            // services.AddRouting(options => options.LowercaseUrls = true);
            services.AddMvc();
            services.AddAntiforgery();
            services.Configure<MvcOptions>(options =>
            {
                options.Filters.Add(new RequireHttpsAttribute());
            });
        }
        catch (Exception ex)
        {
            gFunc.ProcessError(ex);
        }
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        try
        {
            // set file path
            gFunc.SetLogFilePaths(Directory.GetCurrentDirectory());

            // environment
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            app.UseStaticFiles();
            app.UseHttpsRedirection();                
            app.UseRouting();
            app.UseAuthentication();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });

            var provider = new FileExtensionContentTypeProvider();
            provider.Mappings.Add(".exe", "application/octect-stream");

            app.UseStaticFiles(new StaticFileOptions
            {
                FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "canvas")),
                RequestPath = "/canvas",
                ServeUnknownFileTypes = true,
                DefaultContentType = "plain/text",
                ContentTypeProvider = provider
            });

            provider = new FileExtensionContentTypeProvider();
            provider.Mappings.Add(".exe", "application/octect-stream");
            app.UseStaticFiles(new StaticFileOptions
            {
                FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "samadhi")),
                RequestPath = "/samadhi",
                ServeUnknownFileTypes = true,
                DefaultContentType = "plain/text",
                ContentTypeProvider = provider
            });
        }
        catch (Exception ex)
        {
            gFunc.ProcessError(ex);
        }
    }
}

网页配置

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified"/>
      </handlers>
      <aspNetCore processPath="dotnet" arguments=".\Samadhi.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess"/>
    </system.webServer>
  </location>
  <system.web>
    <compilation tempDirectory="C:\Inetpub\vhosts\example.com\tmp"/>
  </system.web>
  <system.webServer>
    <tracing>
      <traceFailedRequests>
        <clear/>
      </traceFailedRequests>
    </tracing>
  </system.webServer>
</configuration>
<!--ProjectGuid: b79c90dc-200d-42a3-a1c4-d3d389a66244-->

标签: asp.net-coreiishttpshttp-status-code-302imageurl

解决方案


傻我!

我站点的一个控制器(一个名为“Samadhi”的控制器)有一个简单地称为“Staff”的路由。我完全忘记了这条路线,当然它与图像路径冲突(静态文件路径:/samadhi/staff/001.jpg)

我将路线重命名为“ManageStaff”,现在图像 url 工作正常。

违规路线:

[HttpGet]
[Authorize(Roles = gFunc.CLAIM_ROLE_SAMADHI_SHOP)]
public async Task<ViewResult> Staff()
{
}

推荐阅读