2013-07-07 34 views
6

Tôi muốn sử dụng các dịch vụ web với Ajax. Cách tốt nhất để bảo mật khi gọi webservice bằng ajax là gì? Tôi muốn bảo vệ khỏi cuộc gọi từ xa trong ứng dụng.Asp.net Webservice - Bảo mật gọi dịch vụ web với jquery AJAX

Tôi đã sau webservice ví dụ:

[WebService(Namespace = "http://tempuri.org/")] 
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 
    [System.ComponentModel.ToolboxItem(false)] 
    [System.Web.Script.Services.ScriptService] 
    public class Users : System.Web.Services.WebService 
    { 

     [WebMethod] 
     public List<User> GetUsers() 
     { 
      List<User> listUsers = new List<User>(); 
      User user = new User(); 
      user.Id = 1; 
      user.Name = "John"; 

      User user2 = new User(); 
      user2.Id = 2; 
      user2.Name = "Martin"; 


      listUsers.Add(user); 
      listUsers.Add(user2); 

      return listUsers; 
     } 
    } 
} 

tôi gọi webservice với jquery ajax:

<script type="text/javascript"> 
    $(function() { 

     getUsers(); 


     function getUsers() { 

      $.ajax({ 
       type: "POST", 

       url: "Webservices/Users.asmx/GetUsers", 

       data: "{}", 

       contentType: "application/json; charset=utf-8", 

       dataType: "json", 

       success: function (response) { 

        var users = response.d; 

        $.each(users, function (index, user) { 

         console.log(user.Name); 

        }); 

       }, 

       failure: function (msg) { 
       } 
      }); 
     } 
    }); 
</script> 
+0

ứng dụng mà các cuộc gọi dịch vụ web là gì? ASP.NET Web Forms, MVC? Là một phần .asmx của cùng một ứng dụng? Ứng dụng web gọi .asmx được bảo mật như thế nào? Bạn có đang sử dụng Xác thực biểu mẫu cho điều đó không? – Badri

+0

@Badri - Cảm ơn bạn đã đặt câu hỏi. Tôi sử dụng ASP.NET Web Forms. Asmx nằm trong cùng một ứng dụng. Tôi làm một ứng dụng trò chuyện và tôi muốn sử dụng dịch vụ web để lưu tin nhắn và truy xuất tin nhắn mới. Tôi muốn thực hiện dịch vụ web an toàn để gửi tin nhắn trò chuyện. Trò chuyện chỉ có thể sử dụng người dùng đã đăng ký. Để xác thực tôi muốn sử dụng xác thực biểu mẫu. – Jenan

Trả lời

9

Không có những điều như cách tốt nhất và câu trả lời luôn luôn là it depends, mặc dù rất vô ích. Bạn có thể sử dụng forms authentication chẳng hạn. Nếu ứng dụng web của bạn sử dụng dịch vụ web và dịch vụ web là một phần của cùng một ASP.NET application, trình duyệt có thể liên tục gửi vé xác thực biểu mẫu (cookie) cho mọi cuộc gọi đến dịch vụ web.

Trong tập tin cấu hình, bạn có thể có

<authorization> 
     <deny users="?" /> 
</authorization> 

này sẽ từ chối truy cập cho người dùng ẩn danh và điều đó sẽ bao gồm các dịch vụ web là tốt. Nói cách khác, trừ khi người dùng đăng nhập và nhận được một cookie hợp lệ với vé, dịch vụ không thể được sử dụng. Tất nhiên, bạn phải HTTPS. Nếu không, bất kỳ một ở giữa có thể nhận được cookie trong các tiêu đề và gọi dịch vụ của bạn.

Cuối cùng, không thể đảm bảo không ai gọi dịch vụ web bên ngoài ứng dụng của bạn theo nghĩa tuyệt đối. Cách tiếp cận trên đảm bảo không có người nào ở giữa gọi dịch vụ của bạn. Nhưng không có cách nào để đảm bảo người dùng hợp lệ gọi dịch vụ trực tiếp bên ngoài ứng dụng của bạn vì người gọi dịch vụ web là JavaScript và bất kỳ bảo mật nào bạn tạo trong JavaScript có thể dễ dàng được người dùng tìm ra bằng cách xem tập lệnh hoặc thậm chí xem lưu lượng truy cập từ và đến trình duyệt. Bất kỳ người dùng cuối nào có chút kỹ thuật, sẽ có thể phát lại yêu cầu hoặc sửa đổi yêu cầu và gửi tới dịch vụ web của bạn bằng thông tin đăng nhập hợp lệ.

EDIT: -

Sau đây là các chi tiết bạn đang tìm kiếm để cho phép FormsAuthentication.

(1) Trong Web.config, dưới <system.web>, đảm bảo bạn có điều này.

<authentication mode="Forms"> 
    <forms loginUrl="Login.aspx" defaultUrl="~/" /> 
</authentication> 
<authorization> 
    <deny users="?" /> 
</authorization> 

Điều này sẽ đảm bảo tất cả người dùng không được xác thực (ẩn danh) được chuyển hướng đến Login.aspx.

(2) Thực hiện Login.aspx với logic đăng nhập của bạn để nhận ID người dùng và mật khẩu và xác thực chúng dựa trên cơ sở dữ liệu hoặc bất kỳ thứ gì. Sau khi xác thực thành công, tức là, người dùng đã nhập ID và mật khẩu khớp với những gì bạn có trong cơ sở dữ liệu, có thể là trong trình xử lý nhấn nút đăng nhập, hãy đặt vé.

protected void Button1_Click(object sender, EventArgs e) 
{ 
    // Do all your login logic here 
    // once user ID and password entered by the user are okay, call this 

    string ticket = FormsAuthentication.Encrypt(
         new FormsAuthenticationTicket("userId", false, 15)); 
    HttpCookie FormsCookie = new HttpCookie(
       FormsAuthentication.FormsCookieName, ticket) { HttpOnly = true }; 
    HttpContext.Current.Response.Cookies.Add(FormsCookie); 
} 

(3) Thêm PrincipalPermissionAttribute vào phương pháp web như thế này.

public class Users : System.Web.Services.WebService 
{ 
    [PrincipalPermissionAttribute(SecurityAction.Demand)] 
    [WebMethod] 
    public List<User> GetUsers() 
    { 
     // Same code as what you have now 
    } 
} 

Nếu bây giờ bạn truy cập bất kỳ trang nào, bạn sẽ được chuyển hướng đến login.aspx nơi bạn sẽ cần nhập ID người dùng và mật khẩu và đăng nhập. Khi đăng nhập, cookie xác thực biểu mẫu sẽ được tạo và ghi vào phản hồi.Từ thời điểm đó trở đi, tất cả các yêu cầu đến ứng dụng của bạn sẽ mang lại cho cookie (trình duyệt sẽ làm điều đó cho bạn). Nếu không đăng nhập, nếu bạn truy cập trực tiếp vào dịch vụ web, bạn sẽ vẫn được chuyển hướng đến trang đăng nhập. Như tôi đã đề cập trong câu trả lời ban đầu của tôi, tuy nhiên người dùng đã đăng nhập vẫn có thể truy cập trực tiếp vào dịch vụ web. Nếu JavaScript có thể làm điều gì đó, người dùng có thể làm như vậy.

BTW, dịch vụ web (asmx) là công nghệ không dùng nữa.

+0

Loại nào hiện được sử dụng thay vì asmx? – Jenan

+0

Cảm ơn bạn rất nhiều vì lời nhắc tuyệt vời của bạn - "dịch vụ web (asmx) là một công nghệ không được chấp nhận". Tôi sử dụng dịch vụ WCF. Bạn có thể chỉnh sửa câu trả lời của bạn cho việc sử dụng dịch vụ wcf không? Cảm ơn bạn. – Jenan

+0

Câu trả lời của tôi sẽ giống với WCF. Đối với pt. # 3, thay vì áp dụng '[PrincipalPermissionAttribute (SecurityAction).Demand)] 'trên phương thức web, áp dụng tương tự trong phương thức của lớp thực hiện hợp đồng dịch vụ WCF. Thay vì WCF, nếu bạn có kế hoạch sử dụng ASP.NET Web API, là một f/w để xây dựng các dịch vụ HTTP, thậm chí sau đó cùng một cách tiếp cận sẽ làm việc. Web API cung cấp một thuộc tính 'Authorize' mà bạn có thể sử dụng thay cho' PrincipalPermission' nhưng về cơ bản, đó là tất cả về việc kiểm tra khai báo nếu có một danh tính được xác thực liên quan đến hiệu trưởng hiện tại. – Badri

1

Một điều bạn có thể làm để giúp ngăn chặn cuộc gọi bên ngoài trình duyệt là đặt mã thông báo dùng một lần vào trang của bạn khi bạn tạo nó, sau đó đăng trong cuộc gọi AJAX của bạn. Việc triển khai đơn giản sẽ là một bảng cơ sở dữ liệu với một loạt các giá trị ngẫu nhiên (có thể là 32 chữ số hoặc tương tự). Khi bạn xây dựng trang, hãy lấy một trong các giá trị từ bảng và đặt nó vào trang của bạn - khi bạn tạo bài đăng biểu mẫu AJAX, hãy bao gồm giá trị đó.

Ở phía máy chủ, đảm bảo giá trị đó tồn tại trong bảng, sau đó xóa giá trị đó khỏi bảng.

Nếu dịch vụ đó được gọi lại với giá trị đó, nó sẽ thất bại vì giá trị không còn trong bảng.

Điều này có nghĩa là để tạo mã thông báo hợp lệ, trước tiên bạn phải nhận được trang và sau đó bạn chỉ có thể sử dụng mã thông báo đó một lần.

Bạn có thể đặt séc bổ sung ở đó như địa chỉ IP, tác nhân người dùng, giá trị cookie, ngày hết hạn, v.v ... và thực hiện những việc như giá trị băm với khóa bí mật hoặc các phương pháp bảo mật khác. Tuy nhiên, cuối cùng, như Badri cho biết, tất cả điều này có thể được giả mạo nếu ai đó thực sự muốn bằng cách đơn giản bằng tay tạo yêu cầu HTTP mà trình duyệt sẽ thực hiện cho cuộc gọi AJAX. Điều tốt nhất bạn có thể làm là đảm bảo rằng chỉ những người dùng hợp lệ mới có thể gọi dịch vụ (bất kể công nghệ khách hàng mà họ đang sử dụng) và điều đó được thực hiện thông qua xác thực biểu mẫu truyền thống.

2

Đây là một chủ đề rất quan trọng để thảo luận. Có thể có nhiều cách để làm điều đó.

Cá nhân chúng tôi sử dụng Ngăn xếp dịch vụ cho API và sử dụng khóa khi chúng tôi truy cập API. Khóa là một guid vẫn giữ nguyên cho Client và Server. Nếu Máy khách và máy chủ là cùng một hệ thống thì sẽ không có bất kỳ sự cố nào khi đăng khóa.

Một cách rất chi tiết để bảo đảm được đưa ra ở đây http://www.stormpath.com/blog/secure-your-rest-api-right-way http://codebetter.com/johnvpetersen/2012/04/02/making-your-asp-net-web-apis-secure/

Cũng ví dụ thêm Building Secure Public API with PHP/MYSQL