2015-10-29 5 views
9
  1. 私はWEBAPIへのアクセスを制限したいapi.example2.com

www.example1.com MVCフロントエンドとWeb API間の偽造トークンを別のドメインに実装するにはどうすればよいですか?

  • WEBAPIプロジェクトのMVCプロジェクトを持っていると思います。 私は偽造トークンを実装しようとしました:

    偽造防止トークンでWebApiへのGET要求を作成すると、要求にこのトークンが含まれていないため例外が発生します。

    ValidateRequestHeaderというメソッドでは、変数cookie = nullです。

    次のコードを修正するにはどうすればよいですか?これは正しい解決策ですか?

    MVCプロジェクト(フロントエンド) - 開発のためにはlocalhost:33635ある:

    Index.cshtml

    <div class="container"> 
    
    
        <div class="row"> 
    
         <div class="col-md-12"> 
    
    
          <input id="get-request-button" type="button" class="btn btn-info" value="Create request to API Server" /> 
    
          <br /> 
    
          <div id="result"></div> 
    
         </div> 
    
    
        </div> 
    
    
    </div> 
    
    
    @section scripts 
    { 
    
        <script type="text/javascript"> 
    
         @functions{ 
          public string TokenHeaderValue() 
          { 
           string cookieToken, formToken; 
           AntiForgery.GetTokens(null, out cookieToken, out formToken); 
           return cookieToken + ":" + formToken; 
          } 
         } 
    
         $(function() { 
    
          $("#get-request-button").click(function() { 
    
           $.ajax("http://localhost:33887/api/values", { 
            type: "GET", 
            contentType: "application/json", 
            data: {}, 
            dataType: "json", 
            headers: { 
             'RequestVerificationToken': '@TokenHeaderValue()' 
            } 
           }).done(function (data) { 
            $("#result").html(data); 
           }); 
    
           return false; 
          }); 
    
         }); 
    
    
        </script> 
    
    } 
    

    WEBAPIプロジェクト - 開発のためにはlocalhost:33887ある:

    WebApiConfig.cs

    public static void Register(HttpConfiguration config) 
         { 
          // Web API configuration and services 
    
          config.EnableCors(new EnableCorsAttribute("http://localhost:33635", "*", "*")); 
    
          // Web API routes 
          config.MapHttpAttributeRoutes(); 
    
          config.Routes.MapHttpRoute(
            name: "DefaultApi", 
            routeTemplate: "api/{controller}/{id}", 
            defaults: new { id = RouteParameter.Optional } 
          ); 
         } 
    

    ValidateHttpAntiForgeryTokenAttribute.cs:

    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)] 
        public sealed class ValidateHttpAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter 
        { 
         public Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation) 
         { 
          var request = actionContext.Request; 
    
          try 
          { 
           if (IsAjaxRequest(request)) 
           { 
            ValidateRequestHeader(request); 
           } 
           else 
           { 
            AntiForgery.Validate(); 
           } 
          } 
          catch (Exception) 
          { 
           actionContext.Response = new HttpResponseMessage 
           { 
            StatusCode = HttpStatusCode.Forbidden, 
            RequestMessage = actionContext.ControllerContext.Request 
           }; 
           return FromResult(actionContext.Response); 
          } 
          return continuation(); 
         } 
    
         private Task<HttpResponseMessage> FromResult(HttpResponseMessage result) 
         { 
          var source = new TaskCompletionSource<HttpResponseMessage>(); 
          source.SetResult(result); 
          return source.Task; 
         } 
    
         private bool IsAjaxRequest(HttpRequestMessage request) 
         { 
          IEnumerable<string> xRequestedWithHeaders; 
          if (!request.Headers.TryGetValues("X-Requested-With", out xRequestedWithHeaders)) return false; 
    
          var headerValue = xRequestedWithHeaders.FirstOrDefault(); 
    
          return !String.IsNullOrEmpty(headerValue) && String.Equals(headerValue, "XMLHttpRequest", StringComparison.OrdinalIgnoreCase); 
         } 
    
         private void ValidateRequestHeader(HttpRequestMessage request) 
         { 
          var headers = request.Headers; 
          var cookie = headers 
            .GetCookies() 
            .Select(c => c[AntiForgeryConfig.CookieName]) 
            .FirstOrDefault(); 
    
          IEnumerable<string> xXsrfHeaders; 
    
          if (headers.TryGetValues("RequestVerificationToken", out xXsrfHeaders)) 
          { 
           var rvt = xXsrfHeaders.FirstOrDefault(); 
    
           if (cookie == null) 
           { 
            throw new InvalidOperationException($"Missing {AntiForgeryConfig.CookieName} cookie"); 
           } 
    
           AntiForgery.Validate(cookie.Value, rvt); 
          } 
          else 
          { 
           var headerBuilder = new StringBuilder(); 
    
           headerBuilder.AppendLine("Missing X-XSRF-Token HTTP header:"); 
    
           foreach (var header in headers) 
           { 
            headerBuilder.AppendFormat("- [{0}] = {1}", header.Key, header.Value); 
            headerBuilder.AppendLine(); 
           } 
    
           throw new InvalidOperationException(headerBuilder.ToString()); 
          } 
         } 
        } 
    

    ValuesController:

    public class ValuesController : ApiController 
        { 
         // GET: api/Values 
         [ValidateHttpAntiForgeryToken] 
         public IEnumerable<string> Get() 
         { 
          return new string[] { "value1", "value2" }; 
         } 
    
         // GET: api/Values/5 
         public string Get(int id) 
         { 
          return "value"; 
         } 
    
         // POST: api/Values 
         public void Post([FromBody]string value) 
         { 
         } 
    
         // PUT: api/Values/5 
         public void Put(int id, [FromBody]string value) 
         { 
         } 
    
         // DELETE: api/Values/5 
         public void Delete(int id) 
         { 
         } 
        } 
    
  • +0

    @teovankot 2台のサーバー間でAntiForgeryTokenの共有を解決したい。あなたのリンクは、1台のサーバー上の偽造トークンだけが解決されます。 – Jenan

    +0

    申し訳ありませんが、私の悪いです –

    答えて

    6

    これは、別のサービスによるアクセスを制限する方法ではありません。 ForgeryTokenは、CSRF攻撃の防止に役立ちます。ASP.NET MVCは、要求検証トークンとも呼ばれる偽造防止トークンを使用します。クライアントは、フォームを含むHTMLページを要求します。サーバーには、応答に2つのトークンが含まれています。 1つのトークンがクッキーとして送信されます。フォームを送信すると、それらは同じサーバー上で一致します。

    私は信じて、あなたが必要とするものはexample1.comからapi.example2.comへの信頼です。 An examplestackauthであり、これはStack Exchange network全体にわたる集中サービスのドメインです。その後、プロジェクトで必要に応じて権限を実装することができます。

    +0

    "信用fronのexample1.comとexample2.com"とはどういう意味ですか - どうすればいいですか?ありがとうございました – Jenan

    +0

    それはあなたのウェブアプリケーションの内部で使用するロジックです。たとえば、現在のアプリケーションによって送信された特定の要求を持つ別のドメインによる認証および認可。 –

    関連する問題