2016-03-08 94 views

回答

3

首先免責聲明:即使你保護你揚鞭UI從大衆消費,你不保護你的API從大衆消費。你必須假定每個人都知道所有的路線,並已經制定了相應的安全保障,其能在任何請求。

話雖這麼說,還是有沒有一個簡單的方法來做到這一點。 Swashbuckle(即增加了招搖的Web API片)將自定義HttpMessageHandler/swagger/ui路線(如圖here)。如果你看看Web API pipeline,你可以看到如果你指定一個自定義處理程序,你可以繞過所有的控制器選擇,Auth過濾器等。這就是發生在這裏的情況。

一些解決方案:

  1. 使用應用程序設置來有條件地ConfigureSwagger(config)僅在調試模式。這將阻止所有/swagger路線投入生產。或者您可以使用臨時插槽並只將其添加到那裏。
  2. 你可以像這樣Basic Auth MessageHandler包裹SwaggerUiHandler。如果他們去/swagger/ui路線,這將提示用戶基本的信用。請參閱下面的代碼我的修改版本。

也許有一點更多的思考,我們可以想出一個更好的解決方案 - 我看到一對夫婦在Swashbuckle回購指示你不打這第一個問題(herehere)。

修改BasicAuthHandler(從here):

警告:微創測試(並且一定要改變你如何驗證用戶名/密碼)

public class BasicAuthMessageHandler : DelegatingHandler 
{ 
    private const string BasicAuthResponseHeader = "WWW-Authenticate"; 
    private const string BasicAuthResponseHeaderValue = "Basic"; 

    public BasicAuthMessageHandler(HttpMessageHandler innerHandler) 
    { 
     this.InnerHandler = innerHandler; 
    } 

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     AuthenticationHeaderValue authValue = request.Headers.Authorization; 
     HttpResponseMessage unauthorizedResponse = request.CreateUnauthorizedResponse(); 

     if (authValue != null && !string.IsNullOrWhiteSpace(authValue.Parameter)) 
     { 
      Credentials parsedCredentials = ParseAuthorizationHeader(authValue.Parameter); 
      if (parsedCredentials != null) 
      { 
       // TODO: Check that the user/pass are valid 
       if (parsedCredentials.Username == "user" && 
        parsedCredentials.Password == "pass") 
       { 
        // If match, pass along to the inner handler 
        return base.SendAsync(request, cancellationToken); 
       } 
      } 
     } 
     else 
     { 
      // Prompt for creds 
      unauthorizedResponse.Headers.Add(BasicAuthResponseHeader, BasicAuthResponseHeaderValue); 
     } 

     return Task.FromResult(unauthorizedResponse); 
    } 

    private Credentials ParseAuthorizationHeader(string authHeader) 
    { 
     string[] credentials = Encoding.ASCII.GetString(Convert 
                 .FromBase64String(authHeader)) 
                 .Split(
                 new[] { ':' }); 
     if (credentials.Length != 2 || string.IsNullOrEmpty(credentials[0]) 
      || string.IsNullOrEmpty(credentials[1])) return null; 
     return new Credentials() 
     { 
      Username = credentials[0], 
      Password = credentials[1], 
     }; 
    } 
} 

與揚鞭路線註冊

// Do this after calling ConfigureSwagger 
ConfigureSwagger(config); 

// Remove the swagger_ui route and re-add it with the wrapped handler. 
var route = config.Routes["swagger_ui"]; 
config.Routes.Remove("swagger_ui"); 
config.Routes.MapHttpRoute("swagger_ui", route.RouteTemplate, route.Defaults, route.Constraints, new BasicAuthMessageHandler(route.Handler)); 
+0

如果我嘗試通過config.Routes.Remove(「swagger_ui」)刪除swagger_ui路由我得到以下錯誤:在System.Web.Http.WebHost.dll中發生類型'System.NotSupportedException'的異常,但未在用戶代碼中處理 附加信息:此操作不受「HostedHttpRouteCollection」支持。 任何想法如何修改路線? –

+0

您是否使用GlobalConfiguration.Configure來設置Web API? http://www.asp.net/web-api/overview/advanced/configuring-aspnet-web-api#webhost。我們的所有示例都使用OWIN自託管(文檔與上一個鏈接位於同一頁面),看起來好像如果通過GlobalConfiguration運行,您將獲得不支持Remove的不同RouteCollection類型。如果這就是你正在做的事情,我可以多調查一下。 – brettsam

+0

是的,我們使用GlobalConfiguration,但我通過替換你的config.Routes.Remove(「swagger_ui」)來修復它。與RouteTable.Routes.Remove(RouteTable.Routes [「swagger_ui」]);現在它的工作 –