2016-06-08 22 views
7

Tôi đã tạo một giải pháp WebAPI mới trong studio trực quan và đang phát xung quanh với mã để thử và hiểu những gì đang xảy ra.WebAPI2.0 Yêu cầu mã thông báo OWIN bằng cách sử dụng JSON

Tôi có một API kiểm tra thats tất cả và chạy với một bộ điều khiển ủy quyền và bộ điều khiển khác thực hiện tất cả các chức năng thực tế.

Các bộ điều khiển (API) tất cả các công việc bằng cách nhận JSON và trả lời với JSON, với ngoại lệ của/Mã request.This phải là:

Content-Type: application/x-www-form-urlencoded 

nếu không tôi chỉ nhận được một lỗi trở lại.

Phần mã mà tạo ra thiết bị đầu cuối này dường như là điều này:

OAuthOptions = new OAuthAuthorizationServerOptions 
{ 
    TokenEndpointPath = new PathString("/Token"), 
    Provider = new ApplicationOAuthProvider(PublicClientId), 
    AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"), 
    AccessTokenExpireTimeSpan = TimeSpan.FromDays(14), 
    // In production mode set AllowInsecureHttp = false 
    AllowInsecureHttp = false 
}; 

Gọi nó như thế này dẫn đến một phản ứng 200 thành công, với một mã thông báo Bearer:

$("#token_button").click(function() 
{ 
    var username = $("#token_email").val(); 
    var password = $("#token_password").val(); 

    postData("Token", "grant_type=password&username=" + username + "&password=" + password, "application/x-www-form-urlencoded", function (data) 
    { 
     user = data; 
     $("#feedback_display").html(user.access_token); 
    }, function() 
    { 
     user = null; 
    }); 
}); 

Gọi nó như điều này dẫn đến 400 phản hồi:

$("#token_button").click(function() 
{ 
    var username = $("#token_email").val(); 
    var password = $("#token_password").val(); 

    var data = { 
     "grant_type": "password", 
     "username": username, 
     "password": password 
    } 

    postData("Token", JSON.stringify(data), "application/json", function (data) 
    { 
     user = data; 
     $("#feedback_display").html(user.access_token); 
    }, function() 
    { 
     user = null; 
    }); 
}); 

Nội dung phản hồi là:

{"error":"unsupported_grant_type"} 

Sự khác biệt duy nhất ở đây là mã hóa được sử dụng để truyền yêu cầu. Mọi nơi tôi xem tất cả các ví dụ đều sử dụng mã hóa biểu mẫu để yêu cầu mã thông báo này.

Đặt điểm ngắt trên mã trong/api/Account/ExternalLogin, không bao giờ bị trúng.

Có lý do nào để điều này chỉ chấp nhận mã hóa biểu mẫu không? và nếu không làm thế nào tôi có thể thay đổi bộ điều khiển để chấp nhận JSON?

Hoặc là tôi vừa làm điều gì đó ngu ngốc?

+1

Không cần phải'JSON.stringify (dữ liệu) ' –

+0

Cảm ơn @gauravbhavsar hoạt động ngay bây giờ. Nếu bạn đăng câu trả lời đó, tôi sẽ đánh dấu là đúng. Tôi đoán rằng làm tăng câu hỏi tại sao tôi cần phải JSON.stringify dữ liệu được đăng lên các thiết bị đầu cuối khác nhưng không phải là một trong những? Tôi chỉ thử nghiệm nó và tôi cần phải. Tôi sẽ đào bới và xem tôi có thể làm được không. – Morvael

Trả lời

11

Lý do đằng sau việc sử dụng application/x-www-form-urlencodedContent-Type rất đơn giản: OAuth2 specification (RFC 6749) yêu cầu loại nội dung này cho yêu cầu mã thông báo.

Bất kỳ loại nội dung nào khác sẽ phá vỡ tính tương thích của máy khách tương thích với OAuth2. Tôi khuyên bạn không nên thay đổi hành vi tiêu chuẩn này.

Note
Xin lưu ý rằng đây:

postData("Token", data, "application/json", function (data) 
{ 
    //... 
} 

công trình chỉ vì bạn đang không gửi JSON ở tất cả! Ngay cả khi bạn thêm application/json làm Content-Type, tiêu đề, phần thân yêu cầu của bạn được tuần tự hóa thành cặp khóa-giá trị biểu mẫu (tuần tự hóa đối tượng mặc định jQuery trong các cuộc gọi AJAX).

Việc thực hiện mặc định của OAuthAuthorizationServerMiddleware (chính xác hơn trong nội bộ sử dụng OAuthAuthorizationServerHandler) từ Microsoft.Owin.Security.OAuth chỉ lờ đi Content-Type tiêu đề và cố gắng để đọc nội dung yêu cầu như một hình thức nào.

+0

Cảm ơn câu trả lời toàn diện. Tôi đã xác minh rằng dữ liệu POST không phải là JSON khi không sử dụng JSON.stringify(). Tôi sẽ làm theo lời khuyên của bạn và để nó được, nó chỉ cười một chút rằng một cuộc gọi này phải được hình thành và phần còn lại JSON. – Morvael

+1

Cảm ơn bạn đã liên kết. Nó đã giúp tôi rất nhiều. đôi khi nó có ý nghĩa hơn để đọc định nghĩa giao thức :) –

1

Không cần phải JSON.stringify(data) bỏ qua dữ liệu direclty.

+0

Cảm ơn một lần nữa vì sự giúp đỡ, tuy nhiên bây giờ tôi hiểu lý do tại sao điều này hoạt động và không cảm thấy tôi có thể đánh dấu điều này là câu trả lời đúng. – Morvael

0

OAuth2 yêu cầu application/x-www-form-urlencoded loại nội dung cho yêu cầu mã thông báo.

Tuy nhiên, tôi nghĩ về cách giải quyết này:

// GET api/Account/GetToken 
    [HttpPost] 
    [AllowAnonymous] 
    [Route("GetToken")] 
    public async Task<IHttpActionResult> GetToken(TokenRequest request) 
    { 
     var client = new HttpClient() 
     { 
      BaseAddress = new Uri(Request.RequestUri.GetLeftPart(UriPartial.Authority)) 
     }; 

     var content = new FormUrlEncodedContent(new[] 
     { 
      new KeyValuePair<string, string>("grant_type", "password"), 
      new KeyValuePair<string, string>("username", request.Username), 
      new KeyValuePair<string, string>("password", request.Password) 
     }); 

     var result = await client.PostAsync("/token", content); 
     string resultContent = await result.Content.ReadAsStringAsync(); 
     resultContent = resultContent.Replace(".issued", "issued").Replace(".expires", "expires"); 
     TokenResponse tokenResponse = JsonConvert.DeserializeObject<TokenResponse>(resultContent); 

     return Ok(tokenResponse); 
    } 

Models:

public class TokenRequest 
    { 
     public string Username { get; set; } 
     public string Password { get; set; } 
    } 

    public class TokenResponse 
    { 
     public string access_token { get; set; } 
     public string token_type { get; set; } 
     public int expires_in { get; set; } 
     public string userName { get; set; } 
     public DateTime issued { get; set; } 
     public DateTime expires { get; set; } 
     public string error { get; set; } 
     public string error_description { get; set; } 
    } 

Nó có thể được cải thiện nhưng hoạt động tuyệt vời.

Các vấn đề liên quan