ASP.NET Core 2.0:在没有控制器的情况下验证路由

时间:2017-10-16 17:12:03

标签: c# authentication routing asp.net-core-mvc swagger

我已在this tutorial之后将Swagger和Swashbuckle生成器添加到我的网站。现在,当导航到fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param HTTPS $https if_not_empty; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; # PHP only, required if PHP was built with --enable-force-cgi-redirect fastcgi_param REDIRECT_STATUS 200; 时,我可以看到生成的API文档。请注意,我没有创建任何fastcgi_split_path_info ^(.+?\.php)(/.*)$; set $path_info $fastcgi_path_info; fastcgi_param PATH_INFO $path_info; try_files $fastcgi_script_name =404; 类 - 这都是由NuGet包处理的。

问题是,我的整个网站,甚至是API,都是使用自定义LDAP进行身份验证的。我也想保护https://localhost:port/swagger/页面。但是,我没有找到办法如何做到这一点。 StackOverflow上唯一相关的问题描述了adding authentication INTO swagger requests - 未对整个API文档页面进行身份验证。

是否有特定的方法来保护生成的SwaggerController页面?或者,是否有一种向ASP.NET Core 2.0 MVC路由添加身份验证验证程序的一般方法?

2 个答案:

答案 0 :(得分:4)

创建一个自定义中间件处理程序,然后将其添加到管道中,如下所示:

<强> Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseMvc();
            app.UseStaticFiles();

            //And here's where the middleware is registered
            app.UseRequestAuthHandler();
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
            });
        }

中间件类:

namespace SwaggerDemo.Handlers
{
    using System.Net;
    using System.Threading.Tasks;

    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Http;

    public class RequestAuthHandler
    {
        private const string _swaggerPathIdentifier = "swagger";
        private readonly RequestDelegate _next;

        public RequestAuthHandler(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            // First check if the current path is the swagger path
            if (context.Request.Path.HasValue && context.Request.Path.Value.ToLower().Contains(_swaggerPathIdentifier))
            {
                // Secondly check if the current user is authenticated
                if (!context.User.Identity.IsAuthenticated)
                {
                    context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                    return;
                }
            }
            await _next.Invoke(context);
        }
    }

    public static class RequestAuthHandlerExtension
    {
        public static IApplicationBuilder UseRequestAuthHandler(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<RequestAuthHandler>();
        }
    }
}

答案 1 :(得分:1)

我想出了以下解决方案:(灵感来自Ryan的解决方案)

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using System;

/// <summary>
/// The extension methods that extends <see cref="IApplicationBuilder" /> for authentication purposes
/// </summary>
public static class ApplicationBuilderExtensions
{
    /// <summary>
    /// Requires authentication for paths that starts with <paramref name="pathPrefix" />
    /// </summary>
    /// <param name="app">The application builder</param>
    /// <param name="pathPrefix">The path prefix</param>
    /// <returns>The application builder</returns>
    public static IApplicationBuilder RequireAuthenticationOn(this IApplicationBuilder app, string pathPrefix)
    {
        return app.Use((context, next) =>
        {
            // First check if the current path is the swagger path
            if (context.Request.Path.HasValue && context.Request.Path.Value.StartsWith(pathPrefix, StringComparison.InvariantCultureIgnoreCase))
            {
                // Secondly check if the current user is authenticated
                if (!context.User.Identity.IsAuthenticated)
                {
                    return context.ChallengeAsync();
                }
            }

            return next();
        });
    }
}

如果您已正确设置身份验证机制,这会将用户重定向到登录页面。

然后,在构建应用程序时(例如,对于NSwag)

app.RequireAuthenticationOn("/swagger");
//Enable Swagger + Swagger Ui
app.UseSwaggerUi3WithApiExplorer(this.ConfigureSwagger);