मैं अपने Google खाते लॉगिन का उपयोग करने के लिए अपने उपयोगकर्ता की आवश्यकता के बिना कैसे अपने ग्राहक (Android, iOS, वेब-एप्लीकेशन) क्लाउड अंतिम बिंदु के साथ प्रमाणित करने पर व्यापक शोध कर रहे हैं जिस तरह से documentation आपको दिखाता है।एक Google खाता लॉगिन बिना मेघ अंतिम बिंदु के लिए अपने ग्राहक प्रमाणित कर रहा है
इसका कारण यह है कि मैं अपने एपीआई को सुरक्षित करना चाहता हूं या केवल मेरे निर्दिष्ट ग्राहकों को "इसे लॉक करना" चाहता हूं। कभी-कभी मेरे पास एक ऐप होगा जिसमें उपयोगकर्ता लॉगिन नहीं होगा। मैं अपने उपयोगकर्ता को अब साइन इन करने के लिए परेशान करता हूं इसलिए मेरा एपीआई सुरक्षित है। या अन्य बार, मैं बस अपने स्वयं के उपयोगकर्ताओं को वेबसाइट पर प्रबंधित करना चाहता हूं और Google+, फेसबुक, या जो कुछ भी लॉगिन प्रमाणीकरण का उपयोग नहीं करना चाहता हूं।
प्रारंभ करने के लिए, मुझे सबसे पहले documentation में निर्दिष्ट Google खाता लॉगिन का उपयोग करके अपने क्लाउड एंडपॉइंट्स एपीआई के साथ अपने एंड्रॉइड ऐप को प्रमाणित करने का तरीका दिखाएं। इसके बाद मैं आपको एक समाधान के लिए अपने निष्कर्ष और संभावित क्षेत्र दिखाऊंगा जिसके लिए मुझे सहायता चाहिए।
(1) अपने एपीआई बैकएंड में अनुरोध करने के लिए अधिकृत ऐप्स के क्लाइंट आईडी (क्लाइंट आईडी) निर्दिष्ट करें और (2) प्रमाणीकरण द्वारा संरक्षित किए जाने वाले सभी खुला तरीकों में उपयोगकर्ता पैरामीटर जोड़ें।
public class Constants {
public static final String WEB_CLIENT_ID = "1-web-apps.apps.googleusercontent.com";
public static final String ANDROID_CLIENT_ID = "2-android-apps.googleusercontent.com";
public static final String IOS_CLIENT_ID = "3-ios-apps.googleusercontent.com";
public static final String ANDROID_AUDIENCE = WEB_CLIENT_ID;
public static final String EMAIL_SCOPE = "https://www.googleapis.com/auth/userinfo.email";
}
import com.google.api.server.spi.auth.common.User; //import for the User object
@Api(name = "myApi", version = "v1",
namespace = @ApiNamespace(ownerDomain = "${endpointOwnerDomain}",
ownerName = "${endpointOwnerDomain}",
packagePath="${endpointPackagePath}"),
scopes = {Constants.EMAIL_SCOPE},
clientIds = {Constants.WEB_CLIENT_ID, Constants.ANDROID_CLIENT_ID,
Constants.IOS_CLIENT_ID,
Constants.API_EXPLORER_CLIENT_ID},
audiences = {Constants.ANDROID_AUDIENCE})
public class MyEndpoint {
/** A simple endpoint method that takes a name and says Hi back */
@ApiMethod(name = "sayHi")
public MyBean sayHi(@Named("name") String name, User user) throws UnauthorizedException {
if (user == null) throw new UnauthorizedException("User is Not Valid");
MyBean response = new MyBean();
response.setData("Hi, " + name);
return response;
}
}
(3) एंड्रॉयड Builder
में credential
चर में पारित करने के लिए सुनिश्चित करने के लिए एक Asynctask में एपीआई विधि कॉल में:
class EndpointsAsyncTask extends AsyncTask<Pair<Context, String>, Void, String> {
private static MyApi myApiService = null;
private Context context;
@Override
protected String doInBackground(Pair<Context, String>... params) {
credential = GoogleAccountCredential.usingAudience(this,
"server:client_id:1-web-app.apps.googleusercontent.com");
credential.setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, null));
if(myApiService == null) { // Only do this once
MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), credential)
// options for running against local devappserver
// - 10.0.2.2 is localhost's IP address in Android emulator
// - turn off compression when running against local devappserver
.setRootUrl("http://<your-app-engine-project-id-here>/_ah/api/")
.setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
@Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
abstractGoogleClientRequest.setDisableGZipContent(true);
}
});
// end options for devappserver
myApiService = builder.build();
}
context = params[0].first;
String name = params[0].second;
try {
return myApiService.sayHi(name).execute().getData();
} catch (IOException e) {
return e.getMessage();
}
}
@Override
protected void onPostExecute(String result) {
Toast.makeText(context, result, Toast.LENGTH_LONG).show();
}
}
क्या हो रहा है कि अपने Android एप्लिकेशन में आप दिखा रहे हैं है Google खाता पिकर पहले, आपके द्वारा Google खाता ईमेल को साझा प्राथमिकताओं में संग्रहीत करता है, और उसके बाद इसे GoogleAccountCredential
ऑब्जेक्ट (here को कैसे करें) के बारे में अधिक जानकारी के रूप में सेट करता है।
Google App Engine सर्वर आपका अनुरोध प्राप्त करता है और इसे जांचता है। यदि एंड्रॉइड क्लाइंट उन 0 में से एक है जिन्हें आपने @Api
नोटेशन में निर्दिष्ट किया है, तो सर्वर com.google.api.server.spi.auth.common.User
ऑब्जेक्ट को आपके एपीआई विधि में इंजेक्ट करेगा। यह जांचना आपकी ज़िम्मेदारी है कि User
ऑब्जेक्ट null
है या आपकी एपीआई विधि के अंदर नहीं है। यदि User
ऑब्जेक्ट null
है, तो आपको इसे चलाने से रोकने के लिए अपनी विधि में अपवाद फेंकना चाहिए। यदि आप यह चेक नहीं करते हैं, तो आपकी एपीआई विधि निष्पादित होगी (यदि आप इसे एक्सेस प्रतिबंधित करने का प्रयास कर रहे हैं तो कोई संख्या नहीं)।
आप अपने Google डेवलपर कंसोल पर जाकर ANDROID_CLIENT_ID
प्राप्त कर सकते हैं। वहां, आप अपने एंड्रॉइड ऐप और SHA1 का पैकेज नाम प्रदान करते हैं जो आपके लिए आपके @Api
एनोटेशन (या इसे Constants
में उपयोगिता के लिए ऊपर निर्दिष्ट की तरह) में उपयोग करने के लिए एक एंड्रॉइड क्लाइंट आईडी उत्पन्न करता है।
मैं ऊपर और यहां के सभी के साथ कुछ व्यापक परीक्षण किया है कि मैं क्या पाया है:
आप अपने @Api
टिप्पणी में फर्जी या अमान्य एंड्रॉयड clientid निर्दिष्ट करते हैं, User
वस्तु में null
हो जाएगा अपने एपीआई विधि। यदि आप if (user == null) throw new UnauthorizedException("User is Not Valid");
के लिए चेक कर रहे हैं तो आपकी एपीआई विधि नहीं चली जाएगी।
यह आश्चर्य की बात है क्योंकि ऐसा लगता है कि क्लाउड एंडपॉइंट्स में दृश्य सत्यापन सत्यापन के पीछे कुछ है जो जांचता है कि एंड्रॉइड क्लाइंटआईड मान्य है या नहीं। यदि यह अमान्य है, तो यह User
ऑब्जेक्ट वापस नहीं करेगा - भले ही अंतिम उपयोगकर्ता अपने Google खाते में लॉग इन हो और GoogleAccountCredential
मान्य था।
मेरा सवाल यह है कि, क्या कोई जानता है कि मैं क्लाउड एंडपॉइंट विधियों में अपने आप के क्लाइंट आईडी सत्यापन के लिए कैसे जांच सकता हूं? क्या यह जानकारी उदाहरण के लिए HttpHeader
में पारित की जा सकती है?
क्लाउड एंडपॉइंट्स में एक और इंजेक्शन प्रकार javax.servlet.http.HttpServletRequest
है। आप इस तरह के अनुरोध को अपने एपीआई विधि में प्राप्त कर सकते हैं:
@ApiMethod(name = "sayHi")
public MyBean sayHi(@Named("name") String name, HttpServletRequest req) throws UnauthorizedException {
String Auth = req.getHeader("Authorization");//always null based on my tests
MyBean response = new MyBean();
response.setData("Hi, " + name);
return response;
}
}
लेकिन मुझे यकीन नहीं है कि आवश्यक जानकारी वहां है या इसे कैसे प्राप्त किया जाए।
निश्चित रूप से कहीं वहाँ कुछ डेटा है, तो ग्राहक एक अधिकृत और @Api
clientIds
में एक निर्दिष्ट है हमें बताता है कि होना चाहिए।
इस तरह, आप अपने एंड्रॉइड ऐप (और संभावित रूप से अन्य क्लाइंट) में अपने एपीआई को लॉक-डाउन कर सकते हैं, बिना किसी अंत में अपने अंतिम उपयोगकर्ताओं को लॉग इन करने के लिए परेशान किए बिना (या बस अपना खुद का सरल उपयोगकर्ता नाम + पासवर्ड लॉगिन बनाएं)।
यह सब हालांकि काम करने के लिए, तो आप इस तरह अपने Builder
का तीसरा तर्क में null
में पारित करने के लिए होगा:
MyApi.Builder बिल्डर = नए MyApi.Builder (AndroidHttp.newCompatibleTransport(), नया एंड्रॉइड जेसनफ़ैक्टरी(), शून्य)
फिर आपके एपीआई विधि में निकाला गया है कि कॉल किसी प्रमाणीकृत क्लाइंट से आया है या नहीं, या तो कोई अपवाद फेंक दें या जो भी कोड आप चाहते हैं उसे चलाएं।
मैं जानता हूँ कि यह संभव है, क्योंकि जब Builder
में एक GoogleAccountCredential
का उपयोग कर, किसी भी तरह मेघ अंतिम बिंदु जानता है या नहीं, कॉल एक प्रमाणीकृत क्लाइंट की ओर से आया था और फिर या तो एपीआई विधि या कि पर आधारित नहीं में अपनी User
वस्तु injects।
क्या यह जानकारी किसी भी तरह हेडर या बॉडी में हो सकती है? यदि हां, तो मैं इसे बाद में जांचने के लिए कैसे प्राप्त कर सकता हूं कि यह मेरी एपीआई विधि में है या नहीं?
नोट: मैंने इस विषय पर अन्य पोस्ट पढ़ी हैं। वे आपके स्वयं के प्रमाणीकरण टोकन में पास करने के तरीके प्रदान करते हैं - जो ठीक है - लेकिन अगर कोई इसे डिमंपाइल करता है तो आपका .apk अभी भी सुरक्षित नहीं होगा। मुझे लगता है कि अगर मेरी परिकल्पना काम करती है, तो आप बिना किसी लॉग इन के क्लाइंट एंडपॉइंट्स एपीआई को क्लाइंट में लॉक-डाउन कर पाएंगे।
Custom Authentication for Google Cloud Endpoints (instead of OAuth2)
Authenticate my "app" to Google Cloud Endpoints not a "user"
Google Cloud Endpoints without Google Accounts
संपादित करें: हम Google मेघ प्लेटफ़ॉर्म के लिए सोने का समर्थन किया जाता है और आगे और पीछे सप्ताह के लिए अपना समर्थन टीम के साथ बात कर दिया गया है। यह हमारे लिए अपने अंतिम जवाब है:।
"दुर्भाग्य से, मैं नहीं इस पर कोई भाग्य पड़ा है मैं अपने टीम के आसपास पूछा है, और प्रलेखन के सभी की जाँच यह का उपयोग कर OAuth2 है जैसा दिखता है। आपका एकमात्र विकल्प। कारण यह है कि एंडपॉइंट सर्वर प्रमाणीकरण को आपके ऐप तक पहुंचने से पहले संभालता है।इसका मतलब है कि आप अपने स्वयं के प्रमाणीकरण प्रवाह को विकसित करने में सक्षम नहीं होंगे, और परिणाम परिणाम प्राप्त करेंगे जो आप टोकन के साथ देख रहे थे।
मुझे आपके लिए एक सुविधा अनुरोध सबमिट करने में खुशी होगी। आप क्यों OAuth2 प्रवाह अपने ग्राहकों के लिए काम करते नहीं करता है के बारे में थोड़ा और अधिक जानकारी प्रदान कर सकता है, मैं बाकी जानकारी के साथ (डाल सकते हैं और उत्पाद प्रबंधक के लिए सबमिट करें। "
उदास चेहरा) - हालांकि, शायद यह अभी भी संभव है?
'req.getHeader (" प्रमाणीकरण ")' null' है यदि आप एंड्रॉइड क्लाइंट से Google प्रमाण पत्र में पास नहीं करते हैं। मैंने 'प्रमाणीकरणकर्ता' के अपने कार्यान्वयन में भी गुजरने का प्रयास किया है, लेकिन समस्या अभी भी मौजूद है: यदि कोई व्यक्ति आपके ऐप को डि-कंपाइल करता है, तो वे आपके ऐप को खराब कर सकते हैं क्योंकि आपके 'प्रमाणक' को काले और सफेद रंग में लिखा गया है ... तो मैं उम्मीद कर रहा था कि कुछ और रास्ता था ... – Micro
@micror यह सच नहीं है। मैंने उपयोगकर्ता परिभाषित मानों (उदाहरण के लिए एक कोणीय जेएस क्लाइंट से) के साथ एथ जैसे कस्टम हेडर पॉप्युलेट किए हैं – jirungaray
कौन सा हिस्सा सत्य नहीं है? हां आप कस्टम हेडर जैसे खुद के द्वारा पॉप्युलेट कर सकते हैं लेकिन तथ्य यह है कि: आपके ऐप को डिमंपिल्ड और स्पूफ किया जा सकता है। कृपया मेरा प्रश्न दोबारा पढ़ें - सवाल दिखाता है कि कुछ प्रकार के प्रमाणीकरण कैसे हैं क्लाउड एंडपॉइंट्स एंड्रॉइड क्लाइंट को सत्यापित करने के लिए कर रहा है कि वे हमें इसके बारे में नहीं बता रहे हैं, इसलिए हम जवाब निकाल सकते हैं। – Micro