【问题标题】:Web API 2 - block all external callsWeb API 2 - 阻止所有外部调用
【发布时间】:2014-09-27 17:16:09
【问题描述】:

是否可以阻止对我的 web api 的所有不是来自网站本身的调用?

我的意思是,如果我的 MVC 应用程序运行在:http://www.domain.com 并且 web api 运行在 http://www.domain.com/api/service,我希望 web api 只接受来自当前应用程序的调用。不允许外部调用。

我猜在这种情况下消息处理程序可能是最好的?

【问题讨论】:

标签: asp.net-mvc-5 asp.net-web-api asp.net-web-api2


【解决方案1】:

为错误页面创建一个控制器并像这样捕获所有垃圾请求:

 config.Routes.MapHttpRoute("block", "{*something}", new { controller = "Error", action = "Get" });

【讨论】:

    【解决方案2】:

    您应该使用委托处理程序来实现令牌授权。

     public class AuthorizationHeaderHandler : DelegatingHandler
    {
        public AuthorizationHeaderHandler(HttpConfiguration httpConfiguration)
        {
    
            //set the inner handler
            InnerHandler = new HttpControllerDispatcher(httpConfiguration); 
        }
    
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            IEnumerable<string> apiKeyHeaderValues = null;
    
            if (request.Headers.TryGetValues("X-ApiKey", out apiKeyHeaderValues))
            {
                var apiKeyHeaderValue = apiKeyHeaderValues.First();
    
                //based on the api-key get username whose session is stil valid.
    
                var username = //code to get user based on apiKeyHeaderValue;
    
                if (!string.IsNullOrEmpty(username))
                {
                    var usernameClaim = new Claim(ClaimTypes.Name, username);
                    var identity = new ClaimsIdentity(new[] {usernameClaim}, "ApiKey");
                    var principal = new ClaimsPrincipal(identity);
    
                    Thread.CurrentPrincipal = principal;
                }
    
            }
            else
            {
                //You don't have an ApiKey from the request... can't proceed
                var response = request.CreateResponse(HttpStatusCode.Forbidden,
                    new {Message = "You are not Authorized to access that resource"}); //new HttpResponseMessage(HttpStatusCode.Forbidden);
                var tsc = new TaskCompletionSource<HttpResponseMessage>();
                tsc.SetResult(response);
                return tsc.Task;
            }
    
            return base.SendAsync(request, cancellationToken);
        }
    }
    

    然后您可以在 WebApiConfig 中注册处理程序

     public class WebApiConfig
    {
        public static void Init(HttpConfiguration config)
        {
    
            config.Routes.MapHttpRoute(
               name: "DefaultApi",
               routeTemplate: "api/{controller}/{action}/{id}",
               defaults: new { id = RouteParameter.Optional },
               constraints:null,
               handler: new AuthorizationHeaderHandler(GlobalConfiguration.Configuration)
           );
    
    
        }
    }
    

    然后你可以设置你的登录控制器来授权用户并分配一个令牌

    public class UserController : ApiController
    {
    
    
    
        public async Task<HttpResponseMessage> Login([FromBody] UserDTO userDTO)
        {
            // first perform user authentication.
    
            // clear all existing tokens for this  authorized user
    
    
            //create security token and save token of current user
            //You can store this in a database and use a repository to create these.
            // Tokens can be guids.  
            // await token creation
    
            return Request.CreateResponse(HttpStatusCode.OK, new {LogingResult = result, token = token});
        }
    }
    

    一旦该用户拥有令牌,就可以通过添加到请求标头来将其用于 Api 请求。在 Angularjs 中,它可以采用以下形式。

    'use strict';
    

    (函数(){

    angular.module('App', ['ngRoute', 'ngCookies']);
    
    //interceptor for server calls
    
    var httpInterceptor = function ($q, $window, $location) {
        return function(promise) {
            var success = function(response) {
                return response;
            };
    
            var error = function(response) {
                if (response.status === 403) {
                    $location.url('/login');
                }
    
                return $q.reject(response);
            };
    
            return promise.then(success, error);
        };
    
    }
    
    httpInterceptor['$inject'] = ['$q', '$window', '$location'];
    angular.module('App').factory('httpInterceptor', httpInterceptor);
    
    
    
    var api = function ($http, $cookies) {
        return {
            init: function (token) {
                $http.defaults.headers.common['X-ApiKey'] = token || $cookies.token;
            }
        };
    }
    
    api['$inject'] = ['$http', '$cookies'];
    
    angular.module('App').factory('api',  api);
    

    })();

    【讨论】:

      【解决方案3】:

      是的,这绝对是可能的。您必须为请求中找到的 RemoteIpAddress 创建自定义处理程序和过滤器。这是使用 Owin Self-Host 的实现:

       public class CustomerHandler : DelegatingHandler
      {
          protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
              CancellationToken cancellationToken)
          {
              if (request?.GetClientIpAddress() != "127.0.0.1")
              {
                  return await Task.FromResult(request.CreateResponse(HttpStatusCode.Unauthorized));
              }
      
              return await base.SendAsync(request, cancellationToken);
          }
      }
      
      public static class HttpReqestMessageExtension
      {
          public static string GetClientIpAddress(this HttpRequestMessage request)
          {
              if (!request.Properties.ContainsKey("MS_OwinContext")) return null;
      
              dynamic owinContext = request.Properties["MS_OwinContext"];
              return owinContext.Request.RemoteIpAddress;
          }
      
      }
      

      如果您使用 ASP.Net,那么您将使用适当的键 => MS_HttpContext

      现在您只需将其添加到您的 Api 的启动中:

      var config = new HttpConfiguration();
      config.MessageHandlers.Add(new CustomerHandler());
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-19
        • 2013-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多