Xác thực người dùng trong API Web ASP.NET


150

Chủ đề này đã vô cùng khó hiểu đối với tôi. Tôi là một tân binh trong các ứng dụng HTTP nhưng cần phát triển ứng dụng khách iPhone tiêu thụ dữ liệu JSON từ đâu đó. Tôi đã chọn API Web từ MS vì nó có vẻ dễ dàng nhưng khi xác thực người dùng, mọi thứ trở nên khá khó chịu.

Tôi ngạc nhiên về việc tôi đã không thể tìm thấy một ví dụ rõ ràng về cách xác thực người dùng ngay từ màn hình đăng nhập cho đến việc sử dụng Authorizethuộc tính trên ApiControllercác phương thức của tôi sau vài giờ Google.

Đây không phải là một câu hỏi mà là một yêu cầu cho một ví dụ về cách làm điều này chính xác. Tôi đã xem các trang sau:

Mặc dù những điều này giải thích cách xử lý các yêu cầu trái phép, nhưng chúng không thể hiện rõ ràng một cái gì đó giống như LoginControllerhoặc một cái gì đó tương tự để yêu cầu thông tin đăng nhập của người dùng và xác thực chúng.

Bất cứ ai sẵn sàng để viết một ví dụ đơn giản tốt đẹp hoặc chỉ cho tôi đi đúng hướng, xin vui lòng?

Cảm ơn.


1
Tôi đã trả lời loại câu hỏi tương tự về vấn đề này: stackoverflow.com/questions/11775594/
Khăn

Đối với Api Web với asp.net, bạn chỉ có thể sử dụng mô-đun cookie và formsauthentication như bạn làm với ứng dụng mvc (nếu bạn muốn). Vì vậy, trong mã api web của bạn, sau đó bạn có thể kiểm tra hiệu trưởng để xem người dùng đã đăng nhập chưa, ví dụ (giống như trước đây).
Elliot

Ngoài ra hãy xem câu trả lời của tôi cho stackoverflow.com/questions/11775594/ từ
Varun Chatterji

Tôi thực sự khuyên nhiều người nên đọc bài viết của asp.net/web-api/overview/security/ .
Youngjae

Câu trả lời:


176

Tôi rất ngạc nhiên khi tôi không thể tìm thấy một ví dụ rõ ràng về cách xác thực người dùng ngay từ màn hình đăng nhập cho đến việc sử dụng thuộc tính Authorize trên các phương thức ApiControll của tôi sau vài giờ Google.

Đó là bởi vì bạn đang bị lẫn lộn về hai khái niệm này:

  • Xác thực là cơ chế theo đó các hệ thống có thể xác định an toàn người dùng của họ. Hệ thống xác thực cung cấp câu trả lời cho các câu hỏi:

    • Ai là người dùng?
    • Người dùng có thực sự là người mà anh ấy / cô ấy thể hiện?
  • Ủy quyền là cơ chế theo đó một hệ thống xác định mức độ truy cập mà người dùng được xác thực cụ thể cần có để bảo đảm các tài nguyên do hệ thống kiểm soát. Ví dụ, một hệ thống quản lý cơ sở dữ liệu có thể được thiết kế để cung cấp cho một số cá nhân được chỉ định khả năng truy xuất thông tin từ cơ sở dữ liệu nhưng không có khả năng thay đổi dữ liệu được lưu trữ trong cơ sở dữ liệu, đồng thời cho các cá nhân khác khả năng thay đổi dữ liệu. Hệ thống ủy quyền cung cấp câu trả lời cho các câu hỏi:

    • Người dùng X có được phép truy cập tài nguyên R không?
    • Người dùng X có được phép thực hiện thao tác P không?
    • Người dùng X có được phép thực hiện thao tác P trên tài nguyên R không?

Các Authorizethuộc tính trong MVC được sử dụng để áp dụng quy tắc truy cập, ví dụ:

 [System.Web.Http.Authorize(Roles = "Admin, Super User")]
 public ActionResult AdministratorsOnly()
 {
     return View();
 }

Quy tắc trên sẽ chỉ cho phép người dùng trong vai trò Quản trị viênSiêu người dùng truy cập phương thức

Các quy tắc này cũng có thể được đặt trong tệp web.config, sử dụng locationphần tử. Thí dụ:

  <location path="Home/AdministratorsOnly">
    <system.web>
      <authorization>
        <allow roles="Administrators"/>
        <deny users="*"/>
      </authorization>
    </system.web>
  </location>

Tuy nhiên, trước khi các quy tắc ủy quyền đó được thực thi, bạn phải được xác thực với trang web hiện tại .

Mặc dù những điều này giải thích làm thế nào để xử lý các yêu cầu trái phép, nhưng chúng không thể hiện rõ ràng một cái gì đó như Đăng nhập hoặc một cái gì đó tương tự để yêu cầu thông tin đăng nhập của người dùng và xác thực chúng.

Từ đây, chúng ta có thể chia vấn đề thành hai:

  • Xác thực người dùng khi sử dụng các dịch vụ API Web trong cùng một ứng dụng Web

    Đây sẽ là cách tiếp cận đơn giản nhất, vì bạn sẽ dựa vào Xác thực trong ASP.Net

    Đây là một ví dụ đơn giản:

    Web.config

    <authentication mode="Forms">
      <forms
        protection="All"
        slidingExpiration="true"
        loginUrl="account/login"
        cookieless="UseCookies"
        enableCrossAppRedirects="false"
        name="cookieName"
      />
    </authentication>
    

    Người dùng sẽ được chuyển hướng đến tuyến tài khoản / đăng nhập , ở đó bạn sẽ hiển thị các điều khiển tùy chỉnh để yêu cầu thông tin đăng nhập của người dùng và sau đó bạn sẽ đặt cookie xác thực bằng cách sử dụng:

        if (ModelState.IsValid)
        {
            if (Membership.ValidateUser(model.UserName, model.Password))
            {
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                return RedirectToAction("Index", "Home");
            }
            else
            {
                ModelState.AddModelError("", "The user name or password provided is incorrect.");
            }
        }
    
        // If we got this far, something failed, redisplay form
        return View(model);
    
  • Xác thực đa nền tảng

    Trường hợp này là khi bạn chỉ hiển thị các dịch vụ API Web trong ứng dụng Web , do đó, bạn sẽ có một khách hàng khác sử dụng các dịch vụ đó, khách hàng có thể là một ứng dụng Web khác hoặc bất kỳ ứng dụng .Net nào (Win Forms, WPF, console, Windows service, Vân vân)

    Ví dụ: giả sử rằng bạn sẽ sử dụng dịch vụ API Web từ một ứng dụng web khác trên cùng một tên miền mạng (trong mạng nội bộ), trong trường hợp này bạn có thể dựa vào xác thực Windows do ASP.Net cung cấp.

    <authentication mode="Windows" />

    Nếu các dịch vụ của bạn được hiển thị trên Internet, thì bạn sẽ cần chuyển các mã thông báo được xác thực cho từng dịch vụ API Web.

    Để biết thêm thông tin, hãy loot các bài viết sau:


3
Ồ Đó là những gì tôi gọi là một câu trả lời. Vì vậy, để kết luận. Tôi đang lên kế hoạch thực hiện các bước sau: 1. Tạo bộ điều khiển tài khoản bằng phương thức Đăng nhập nhận tên người dùng và mật khẩu qua HTTPS và trả về kết quả đăng nhập và mã thông báo. 2. Máy khách lưu trữ mã thông báo và gửi dưới dạng tiêu đề (không còn HTTPS nữa) trong yêu cầu được xác thực bởi máy chủ web. Đó có phải là một cách tiếp cận tốt? Sau đó, nghi ngờ cuối cùng của tôi là làm thế nào để kiểm soát mã thông báo giả mạo và hết hạn. Điều này có thể không?
Luis Aguilar

6
@Jupaol Tôi nghĩ rằng tôi nói cho nhiều nhà phát triển API Web, tôi không thể sử dụng Xác thực Mẫu vì tôi không có trang web và khách hàng không sử dụng trình duyệt, tôi cũng không thể sử dụng Xác thực tích hợp vì người dùng có thể ở bất kỳ đâu trên thế giới trên mọi thiết bị ( do đó API Web), vậy tôi sẽ sử dụng cái gì?
markmnl

21
Tôi không hiểu tại sao câu trả lời này nhận được rất nhiều upvote. Đó không phải là về API Web ASP.NET mà là về ASP.NET MVC.
Bastien Vandamme

3
Tôi muốn nhắc lại nhận xét của B413 và chỉ ra rằng câu hỏi này đặc biệt yêu cầu API Web
Julien

6
Đây có phải là câu trả lời 'sai' được bình chọn nhiều nhất trên SO? Câu trả lời không thực sự nói về api web rất khác với ứng dụng web mvc! Giống như @ B413 tôi hoàn toàn sốc!
stt106

15

Nếu bạn muốn xác thực với tên người dùng và mật khẩukhông có cookie ủy quyền , thuộc tính ủy quyền MVC4 sẽ không hoạt động. Tuy nhiên, bạn có thể thêm phương thức trợ giúp sau vào bộ điều khiển của mình để chấp nhận các tiêu đề xác thực cơ bản. Gọi nó từ đầu phương thức của bộ điều khiển của bạn.

void EnsureAuthenticated(string role)
{
    string[] parts = UTF8Encoding.UTF8.GetString(Convert.FromBase64String(Request.Headers.Authorization.Parameter)).Split(':');
    if (parts.Length != 2 || !Membership.ValidateUser(parts[0], parts[1]))
        throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "No account with that username and password"));
    if (role != null && !Roles.IsUserInRole(parts[0], role))
        throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "An administrator account is required"));
}

Từ phía máy khách, trình trợ giúp này tạo một HttpClienttiêu đề xác thực tại chỗ:

static HttpClient CreateBasicAuthenticationHttpClient(string userName, string password)
{
    var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(UTF8Encoding.UTF8.GetBytes(userName + ':' + password)));
    return client;
}

Chỉ muốn nhận xét rằng tôi đang tìm kiếm một cách đơn giản để sử dụng tiêu chuẩn ngành để vượt qua thông tin đăng nhập trong tiêu đề. Ví dụ này cho thấy những điều cơ bản từ cả máy chủ và phía máy khách và là tất cả những gì tôi cần.
da_jokker

9

Tôi đang làm việc trên một dự án API MVC / Web và cần thiết để có thể có được ủy quyền cho các phương thức Api Web. Khi chế độ xem chỉ mục của tôi được tải lần đầu tiên, tôi thực hiện cuộc gọi đến phương thức API Web 'token' mà tôi tin là được tạo tự động.

Mã phía máy khách (CoffeeScript) để nhận mã thông báo là:

getAuthenticationToken = (username, password) ->
    dataToSend = "username=" + username + "&password=" + password
    dataToSend += "&grant_type=password"
    $.post("/token", dataToSend).success saveAccessToken

Nếu thành công, phần sau được gọi, sẽ lưu mã xác thực cục bộ:

saveAccessToken = (response) ->
    window.authenticationToken = response.access_token

Sau đó, nếu tôi cần thực hiện cuộc gọi Ajax tới phương thức API Web có thẻ [Ủy quyền], tôi chỉ cần thêm tiêu đề sau vào cuộc gọi Ajax của mình:

{ "Authorization": "Bearer " + window.authenticationToken }

Từ đâu response.access_tokenđến từ đâu. Bạn đang thiết lập nó từ mã c # ..?
shashwat

Đối tượng 'phản hồi' được trả về bằng phương thức 'mã thông báo'.
ProfNimrod

Tôi đã không nhìn vào vai trò. Cách tiếp cận này chỉ cung cấp cho bạn mã thông báo truy cập để bạn có thể gọi các phương thức WebApi được trang trí bằng thẻ [Ủy quyền]. Trước đây, khi bạn gọi bất kỳ phương thức nào bạn có thể kiểm tra vai trò. stackoverflow.com/questions/19689570/mvc-5-check-user-role có thể giúp ích.
ProfNimrod

Và nơi nào trong giải pháp này bạn thực sự xác thực người dùng của bạn?
Craig Brett

Điểm cuối / mã thông báo được tạo tự động cho bất kỳ dự án API Web mới nào. Mã đằng sau này là nơi người dùng được xác thực. Sẽ phức tạp hơn một chút nếu bạn đã thêm bộ điều khiển API Web vào dự án MVC hiện có.
ProfNimrod
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.