2013-06-03 34 views
21

API là phụ trợ cho ứng dụng dành cho thiết bị di động. Tôi không cần xác thực người dùng. Tôi chỉ cần một cách để bảo mật quyền truy cập vào API này. Hiện tại, chương trình phụ trợ của tôi đã được hiển thị.Làm cách nào để bảo vệ API của tôi được tạo bằng Google Cloud Endpoints?

documentation dường như chỉ nói về xác thực và ủy quyền người dùng, đó không phải là những gì tôi cần ở đây. Tôi chỉ cần đảm bảo rằng ứng dụng di động của tôi có thể nói chuyện với chương trình phụ trợ này và không ai khác.

+0

Trên thực tế bạn đang nói về xác thực và ủy quyền . Làm thế nào bạn sẽ đề xuất bảo vệ một điểm cuối cho chỉ ứng dụng của bạn mà không có một số hình thức xác thực, (hoặc ứng dụng hoặc người dùng cuối). Điểm cuối chỉ là các dịch vụ web tuân theo api công khai cụ thể. –

+0

Một ví dụ về cách làm việc này là Tài khoản dịch vụ: https://developers.google.com/accounts/docs/OAuth2ServiceAccount Tuy nhiên, đây chỉ là cho API của Google. Tài liệu chỉ dành cho khách hàng. Những gì tôi cần là tài liệu hướng dẫn về cách cung cấp chức năng Tài khoản dịch vụ ở phía máy chủ. – mixmasteralan

+0

Một cách khác là sử dụng giá trị băm của riêng bạn giữa ứng dụng và điểm cuối của bạn http://stackoverflow.com/questions/2447470/recaptcha-on-iphone-app-using-sdk – Ton

Trả lời

4

Có, bạn có thể làm điều đó: sử dụng xác thực để bảo mật điểm cuối của bạn mà không cần xác thực người dùng.

Tôi đã nhận thấy rằng cách làm này không được ghi chép đầy đủ và tôi chưa thực sự tự làm, nhưng tôi dự định sẽ chú ý khi thấy nó được thảo luận trên một số video IO13 (I nghĩ đó là nơi tôi nhìn thấy nó):

Dưới đây là sự hiểu biết của tôi về những gì đang tham gia:

  • Tạo một dự án Google API (mặc dù điều này không thực sự liên quan đến của API của họ, trừ xác thực chính nó).
  • Tạo ID khách hàng OATH được liên kết với ứng dụng của bạn thông qua tên gói và dấu vân tay SHA1 của chứng chỉ mà bạn sẽ ký ứng dụng.

Bạn sẽ thêm các ID khách hàng này vào danh sách ID có thể chấp nhận cho điểm cuối của bạn. Bạn sẽ thêm tham số User vào các điểm cuối của bạn, nhưng nó sẽ là null vì không có người dùng nào được chỉ định.

@ApiMethod(
    name = "sendInfo", 
    clientIds = { Config.WEB_CLIENT_ID, Config.MY_APP_CLIENT_ID, Config.MY_DEBUG_CLIENT_ID }, 
    audiences = { Config.WEB_CLIENT_ID } 
    // Yes, you specify a 'web' ID even if this isn't a Web client. 
) 
public void sendInfo(User user, Info greeting) { 

Có một số tài liệu phong nha về việc trên, ở đây: https://developers.google.com/appengine/docs/java/endpoints/auth

ứng dụng Khách hàng của bạn sẽ xác định những khách hàng ID khi xây dựng các cuộc gọi dịch vụ thiết bị đầu cuối. Tất cả các chi tiết OATH sẽ được đưa về phía sau hậu trường trên thiết bị khách của bạn sao cho ID khách hàng của bạn được dịch sang mã thông báo xác thực.

HttpTransport transport = AndroidHttp.newCompatibleTransport(); 
JsonFactory jsonFactory = new JacksonFactory(); 
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience(ctx, Config.WEB_CLIENT_ID); 
//credential.setSelectedAccountName(user); // not specify a user 
Myendpoint.Builder builder = new Myendpoint.Builder(transport, jsonFactory, credential); 

Mã khách hàng này chỉ là dự đoán tốt nhất của tôi - xin lỗi. Nếu bất cứ ai khác có một tham chiếu cho chính xác những gì mã khách hàng nên trông như thế thì tôi cũng sẽ được quan tâm.

+1

Bạn không thể "không chỉ định người dùng" trong thông tin xác thực .setSelectedAccountName(); - cần một đối số chuỗi bắt buộc ... – Micro

+1

Bạn đã thử cái này chưa? Hy vọng bạn đã viết câu trả lời này sau khi thử. – Bharathi

+1

Tom: Việc này có hiệu quả với bạn không? @MicroR: Bạn đang nói rằng nó sẽ lấy chuỗi rỗng? – sam

2

Tôi rất tiếc phải nói rằng Google không cung cấp giải pháp cho vấn đề của bạn (cũng là vấn đề của tôi). Bạn có thể sử dụng cơ chế khóa API của chúng (xem https://developers.google.com/console/help/new/#usingkeys), nhưng có một lỗ hổng lớn trong chiến lược này bởi trình thám hiểm API của Google (xem https://developers.google.com/apis-explorer/#p/), một công cụ phát triển tuyệt vời để kiểm tra API, nhưng hiển thị tất cả API của Cloud Endpoint, không chỉ API của các dịch vụ của Google. Điều này có nghĩa là bất kỳ ai có tên dự án của bạn đều có thể duyệt và gọi API của bạn khi họ rảnh rỗi vì trình khám phá API phá vỡ bảo mật khóa API. Tôi tìm thấy cách giải quyết khác (dựa trên phản hồi tuyệt vời của bossylobster đối với bài đăng này: Simple Access API (Developer Key) with Google Cloud Endpoint (Python)), để chuyển trường yêu cầu không phải là một phần của định nghĩa yêu cầu thư trong API ứng dụng khách của bạn và sau đó đọc nó trong máy chủ API của bạn. Nếu bạn không tìm thấy trường không có giấy tờ, bạn sẽ tăng ngoại lệ trái phép. Thao tác này sẽ cắm lỗ do trình khám phá API tạo ra. Trong iOS (mà tôi đang sử dụng cho các ứng dụng của tôi), bạn thêm thuộc tính cho mỗi lớp theo yêu cầu (những người tạo ra bởi công cụ phát API của Google) như sau:

@property (copy) NSString *hiddenProperty; 

và đặt giá trị là một chìa khóa mà bạn chọn.Trong mã máy chủ của bạn (python trong trường hợp của tôi), bạn kiểm tra xem có tồn tại của nó và barf nếu bạn không nhìn thấy nó hoặc nó không được thiết lập với giá trị mà máy chủ và khách hàng của bạn sẽ đồng ý về:

mykey,keytype = request.get_unrecognized_field_info('hiddenProperty') 
     if mykey != 'my_supersecret_key': 
      raise endpoints.UnauthorizedException('No, you dont!') 

Hope puts này bạn đi đúng hướng

+0

Nhưng nếu ai đó giải mã APK Android của bạn, họ có thể chỉ nhìn thấy trường yêu cầu văn bản thuần túy và sau đó tạo một ứng dụng Android khác và chơi với API của bạn không? Trong javascript nó sẽ dễ dàng hơn vì bạn chỉ có thể xem nguồn. – Micro

+0

Tôi không quen với APK hoặc cách dễ dàng để dịch ngược. Trong trường hợp của tôi, một ứng dụng iOS khá khó để cố gắng lấy mã thực hiện điều này. –

+0

@MicroR Ở phía máy khách có thể được tạo ra phương pháp bán phức tạp mà cuối cùng tạo ra một số, ví dụ, giá trị dài đơn giản được gửi đến máy chủ. Sau khi bị làm xáo trộn, thậm chí bị dịch ngược, nó sẽ trông giống như những hành động số học không có ý nghĩa. Và về phía máy chủ kiểm tra nếu nhận được giá trị sau khi được xác định trước tập hợp các hành động khác được chia trên, hãy nói 17. – yurin

2

Tài liệu chỉ dành cho khách hàng. Những gì tôi cần là tài liệu về cách cung cấp chức năng Tài khoản dịch vụ ở phía máy chủ.

Điều này có thể có nghĩa là một vài điều khác nhau, nhưng tôi muốn giải quyết những gì tôi nghĩ câu hỏi đang đặt ra. Nếu bạn chỉ muốn tài khoản dịch vụ truy cập dịch vụ của mình, thì bạn chỉ có thể thêm clientId của tài khoản dịch vụ vào các chú thích @ Api/@ ApiMethod, tạo GoogleCredential và gọi dịch vụ của bạn như bình thường. Cụ thể ...

Trong bảng điều khiển dành cho nhà phát triển của Google, hãy tạo tài khoản dịch vụ mới. Thao tác này sẽ tạo tệp .p12 được tải xuống tự động. Điều này được khách hàng sử dụng trong tài liệu bạn đã liên kết đến. Nếu bạn không thể giữ an toàn .p12, thì điều này không an toàn hơn nhiều so với mật khẩu. Tôi đoán đó là lý do tại sao điều này không được trình bày rõ ràng trong tài liệu về Thiết bị đầu cuối đám mây.

Bạn thêm ID KHÁCH HÀNG hiển thị trong giao diện điều khiển các nhà phát triển của Google để các clientIds trong @Api hoặc chú thích @ApiMethod

import com.google.appengine.api.users.User 

@ApiMethod(name = "doIt", scopes = { Constants.EMAIL_SCOPE }, 
    clientIds = { "12345678901-12acg1ez8lf51spfl06lznd1dsasdfj.apps.googleusercontent.com" }) 
public void doIt(User user){ //by convention, add User parameter to existing params 
    // if no client id is passed or the oauth2 token doesn't 
    // match your clientId then user will be null and the dev server 
    // will print a warning message like this: 
    // WARNING: getCurrentUser: clientId 1234654321.apps.googleusercontent.com not allowed 
    //.. 
} 

Bạn xây dựng một khách hàng giống như cách bạn làm với phiên bản không có bảo đảm, sự khác biệt duy là bạn tạo một đối tượng GoogleCredential để chuyển tới MyService.Builder của dịch vụ của bạn.

HttpTransport httpTransport = new NetHttpTransport(); // or build AndroidHttpClient on Android however you wish 
JsonFactory jsonFactory = new JacksonFactory(); 

// assuming you put the .p12 for your service acccount 
// (from the developer's console) on the classpath; 
// when you deploy you'll have to figure out where you are really 
// going to put this and load it in the appropriate manner 
URL url = getClass().class.getResource("/YOURAPP-b12345677654.p12"); 
File p12file = new File(url.toURI()); 

GoogleCredential.Builder credentialBuilder = new GoogleCredential.Builder(); 
credentialBuilder.setTransport(httpTransport); 
credentialBuilder.setJsonFactory(jsonFactory); 
//NOTE: use service account EMAIL (not client id) 
credentialBuilder.setServiceAccountId("[email protected]serviceaccount.com"); credentialBuilder.setServiceAccountScopes(Collections.singleton("https://www.googleapis.com/auth/userinfo.email")); 
credentialBuilder.setServiceAccountPrivateKeyFromP12File(p12file); 
GoogleCredential credential = credentialBuilder.build(); 

Bây giờ gọi khách hàng được tạo ra theo cách tương tự bạn mong các phiên bản không có bảo đảm, trừ trường hợp những người xây dựng mất google chứng chỉ của chúng tôi từ trên cao như là đối số cuối cùng

MyService.Builder builder = new MyService.Builder(httpTransport, jsonFactory, credential); 
builder.setApplicationName("APP NAME"); 
builder.setRootUrl("http://localhost:8080/_ah/api"); 

final MyService service = builder.build(); 
// invoke service same as unsecured version 
+0

Tom, tôi đang cố gắng này trên dev, nhưng người dùng được thông qua luôn luôn là null, mặc dù ủy quyền được thực hiện bằng cách sử dụng id email của tôi được sử dụng trong dự án GAE. Id ứng dụng mà tôi đã cung cấp trong @Apimethod không nên là sai kể từ khi tôi thành công sử dụng nó để truy cập lưu trữ đám mây google. Bạn đã làm việc này chưa? – maya

+0

Điều này không hoạt động. Tôi đã cố gắng cho khách hàng web. Nhưng tôi có thể gọi điện từ bất kỳ khách hàng nào. Có lẽ nó sẽ chặn khách hàng khác với id khách hàng của tôi. Nhưng nó không. – Bharathi

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