Xác thực API Web ASP.NET


122

Tôi đang tìm cách xác thực người dùng từ ứng dụng khách khi sử dụng API Web ASP.NET . Tôi đã xem tất cả các video trên trang web và cũng đọc bài đăng trên diễn đàn này .

Đặt [Authorize]thuộc tính một cách chính xác sẽ trả về một 401 Unauthorizedtrạng thái. Tuy nhiên, tôi cần biết cách cho phép người dùng đăng nhập vào API.

Tôi muốn cung cấp thông tin đăng nhập của người dùng từ một ứng dụng Android cho API, giúp người dùng đăng nhập và sau đó xác thực trước tất cả các lệnh gọi API tiếp theo.


Chào Mujtaba. Bạn có thể thực hiện điều này không?
Vivek Chandraprakash

Trước tiên, hãy sử dụng CORS để ngăn chặn lần truy cập không mong muốn từ miền khác. Sau đó, gửi một cookie Xác thực Mẫu hợp lệ cùng với yêu cầu và cuối cùng ủy quyền yêu cầu bằng mã thông báo. Sự kết hợp này luôn làm cho api web của bạn an toàn và tối ưu hóa.
Majedur Rahaman

Câu trả lời:


137

cho phép người dùng đăng nhập vào API

Bạn cần gửi một cookie Xác thực Mẫu hợp lệ cùng với yêu cầu. Cookie này thường được gửi bởi máy chủ khi xác thực ( LogOnhành động) bằng cách gọi [FormsAuthentication.SetAuthCookiephương thức (xem MSDN ).

Vì vậy, khách hàng cần thực hiện 2 bước:

  1. Gửi một yêu cầu HTTP cho một LogOnhành động bằng cách gửi tên người dùng và mật khẩu. Đổi lại, hành động này sẽ gọi FormsAuthentication.SetAuthCookiephương thức (trong trường hợp thông tin xác thực hợp lệ), từ đó sẽ đặt cookie xác thực biểu mẫu trong phản hồi.
  2. Gửi yêu cầu HTTP đến một [Authorize]hành động được bảo vệ bằng cách gửi cùng cookie xác thực biểu mẫu mà nó đã truy xuất trong yêu cầu đầu tiên.

Hãy lấy một ví dụ. Giả sử rằng bạn có 2 bộ điều khiển API được xác định trong ứng dụng web của mình:

Người đầu tiên chịu trách nhiệm xử lý xác thực:

public class AccountController : ApiController
{
    public bool Post(LogOnModel model)
    {
        if (model.Username == "john" && model.Password == "secret")
        {
            FormsAuthentication.SetAuthCookie(model.Username, false);
            return true;
        }

        return false;
    }
}

và cái thứ hai chứa các hành động được bảo vệ mà chỉ người dùng được ủy quyền mới có thể xem:

[Authorize]
public class UsersController : ApiController
{
    public string Get()
    {
        return "This is a top secret material that only authorized users can see";
    }
}

Bây giờ chúng ta có thể viết một ứng dụng khách sử dụng API này. Đây là một ví dụ ứng dụng bảng điều khiển nhỏ (đảm bảo bạn đã cài đặt các gói Microsoft.AspNet.WebApi.ClientMicrosoft.Net.HttpNuGet):

using System;
using System.Net.Http;
using System.Threading;

class Program
{
    static void Main()
    {
        using (var httpClient = new HttpClient())
        {
            var response = httpClient.PostAsJsonAsync(
                "http://localhost:26845/api/account", 
                new { username = "john", password = "secret" }, 
                CancellationToken.None
            ).Result;
            response.EnsureSuccessStatusCode();

            bool success = response.Content.ReadAsAsync<bool>().Result;
            if (success)
            {
                var secret = httpClient.GetStringAsync("http://localhost:26845/api/users");
                Console.WriteLine(secret.Result);
            }
            else
            {
                Console.WriteLine("Sorry you provided wrong credentials");
            }
        }
    }
}

Và đây là cách 2 yêu cầu HTTP trông như thế nào trên dây:

Yêu cầu xác thực:

POST /api/account HTTP/1.1
Content-Type: application/json; charset=utf-8
Host: localhost:26845
Content-Length: 39
Connection: Keep-Alive

{"username":"john","password":"secret"}

Phản hồi xác thực:

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Wed, 13 Jun 2012 13:24:41 GMT
X-AspNet-Version: 4.0.30319
Set-Cookie: .ASPXAUTH=REMOVED FOR BREVITY; path=/; HttpOnly
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Content-Type: application/json; charset=utf-8
Content-Length: 4
Connection: Close

true

Yêu cầu dữ liệu được bảo vệ:

GET /api/users HTTP/1.1
Host: localhost:26845
Cookie: .ASPXAUTH=REMOVED FOR BREVITY

Phản hồi cho dữ liệu được bảo vệ:

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Wed, 13 Jun 2012 13:24:41 GMT
X-AspNet-Version: 4.0.30319
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Content-Type: application/json; charset=utf-8
Content-Length: 66
Connection: Close

"This is a top secret material that only authorized users can see"

Nó sẽ duy trì một phiên cho ứng dụng Android?
Mujtaba Hassan

Đã hiểu nhưng bạn có thể vui lòng đăng mã mẫu cho điểm thứ hai. Cảm ơn câu trả lời của bạn.
Mujtaba Hassan

2
Viết một ứng dụng HTTP Android là một chủ đề cho một câu hỏi khác. Nó không liên quan đến ASP.NET MVC và ASP.NET MVC Web API, đó là câu hỏi của bạn. Tôi khuyên bạn nên bắt đầu một chuỗi mới gắn thẻ rõ ràng với Java và Android, trong đó bạn hỏi về cách viết một ứng dụng khách HTTP gửi yêu cầu bằng cookie.
Darin Dimitrov

Trên thực tế, trong tài liệu về MVC4 WebApi, họ đã viết rằng WebAPI là mục tiêu cho các khách hàng bên thứ ba, đặc biệt là các khách hàng di động (và tất nhiên là như vậy). Giả sử chúng tôi có một ứng dụng khách dành cho máy tính để bàn, bạn có thể đăng một đoạn mã đơn giản được không. Cảm ơn
Mujtaba Hassan

2
Cũng thấy câu hỏi này (và câu trả lời) về việc sử dụng xác thực HTTP cơ bản: stackoverflow.com/questions/10987455/...
Jim Harte

12

Tôi lấy android làm ví dụ.

public abstract class HttpHelper {

private final static String TAG = "HttpHelper";
private final static String API_URL = "http://your.url/api/";

private static CookieStore sCookieStore;

public static String invokePost(String action, List<NameValuePair> params) {
    try {
        String url = API_URL + action + "/";
        Log.d(TAG, "url is" + url);
        HttpPost httpPost = new HttpPost(url);
        if (params != null && params.size() > 0) {
            HttpEntity entity = new UrlEncodedFormEntity(params, "UTF-8");
            httpPost.setEntity(entity);
        }
        return invoke(httpPost);
    } catch (Exception e) {
        Log.e(TAG, e.toString());
    }

    return null;
}

public static String invokePost(String action) {
    return invokePost(action, null);
}

public static String invokeGet(String action, List<NameValuePair> params) {
    try {
        StringBuilder sb = new StringBuilder(API_URL);
        sb.append(action);
        if (params != null) {
            for (NameValuePair param : params) {
                sb.append("?");
                sb.append(param.getName());
                sb.append("=");
                sb.append(param.getValue());
            }
        }
        Log.d(TAG, "url is" + sb.toString());
        HttpGet httpGet = new HttpGet(sb.toString());
        return invoke(httpGet);
    } catch (Exception e) {
        Log.e(TAG, e.toString());
    }

    return null;
}

public static String invokeGet(String action) {
    return invokeGet(action, null);
}

private static String invoke(HttpUriRequest request)
        throws ClientProtocolException, IOException {
    String result = null;
    DefaultHttpClient httpClient = new DefaultHttpClient();

    // restore cookie
    if (sCookieStore != null) {
        httpClient.setCookieStore(sCookieStore);
    }

    HttpResponse response = httpClient.execute(request);

    StringBuilder builder = new StringBuilder();
    BufferedReader reader = new BufferedReader(new InputStreamReader(
            response.getEntity().getContent()));
    for (String s = reader.readLine(); s != null; s = reader.readLine()) {
        builder.append(s);
    }
    result = builder.toString();
    Log.d(TAG, "result is ( " + result + " )");

    // store cookie
    sCookieStore = ((AbstractHttpClient) httpClient).getCookieStore();
    return result;
}

Xin lưu ý : i.localhost không thể được sử dụng. Thiết bị Android giống như máy chủ lưu trữ cục bộ. ii.Nếu triển khai API web trong IIS, xác thực Biểu mẫu phải được mở.


0

Sử dụng mã này và truy cập cơ sở dữ liệu

[HttpPost]
[Route("login")]
public IHttpActionResult Login(LoginRequest request)
{
       CheckModelState();
       ApiResponse<LoginApiResponse> response = new ApiResponse<LoginApiResponse>();
       LoginResponse user;
       var count = 0;
       RoleName roleName = new RoleName();
       using (var authManager = InspectorBusinessFacade.GetAuthManagerInstance())
       {
           user = authManager.Authenticate(request); 
       } reponse(ok) 
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.