نمای کلی
هدف: این سند نحوه استفاده از کلاس ابزار GoogleCredential برای انجام مجوز OAuth 2.0 با خدمات Google را توضیح می دهد. برای اطلاعات در مورد توابع عمومی OAuth 2.0 که ارائه می کنیم، OAuth 2.0 و Google OAuth Client Library برای جاوا را ببینید.
خلاصه: برای دسترسی به داده های محافظت شده ذخیره شده در سرویس های Google، از OAuth 2.0 برای مجوز استفاده کنید. API های Google از جریان های OAuth 2.0 برای انواع مختلف برنامه های مشتری پشتیبانی می کنند. در تمام این جریانها، برنامه مشتری یک نشانه دسترسی را درخواست میکند که فقط با برنامه مشتری شما و مالک دادههای محافظتشده در حال دسترسی مرتبط است. نشانه دسترسی همچنین با محدوده محدودی مرتبط است که نوع دادههایی را که برنامه مشتری شما به آن دسترسی دارد را مشخص میکند (به عنوان مثال "مدیریت وظایف خود"). یک هدف مهم برای OAuth 2.0 این است که دسترسی ایمن و راحت به داده های محافظت شده را فراهم کند، در حالی که تأثیر احتمالی در صورت سرقت توکن دسترسی را به حداقل می رساند.
بستههای OAuth 2.0 در Google API Client Library برای جاوا بر اساس Google OAuth 2.0 Client Library برای جاوا ساخته شدهاند.
برای جزئیات، به مستندات Javadoc برای بسته های زیر مراجعه کنید:
- com.google.api.client.googleapis.auth.oauth2 (از google-api-client )
- com.google.api.client.googleapis.extensions.appengine.auth.oauth2 (از google-api-client-appengine )
کنسول API Google
قبل از اینکه بتوانید به Google API دسترسی داشته باشید، باید پروژهای را در Google API Console برای اهداف احراز هویت و صورتحساب راهاندازی کنید، خواه کلاینت شما یک برنامه نصبشده باشد، یک برنامه تلفن همراه، یک وب سرور یا یک کلاینت که در مرورگر اجرا میشود.
برای دستورالعملهای مربوط به تنظیم صحیح اطلاعات کاربری خود، به راهنمای کنسول API مراجعه کنید.
اعتبارنامه
اعتبار Google
GoogleCredential یک کلاس کمکی ایمن رشته ای برای OAuth 2.0 برای دسترسی به منابع محافظت شده با استفاده از یک نشانه دسترسی است. به عنوان مثال، اگر قبلاً یک نشانه دسترسی دارید، می توانید به روش زیر درخواست دهید:
GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken); Plus plus = new Plus.builder(new NetHttpTransport(), GsonFactory.getDefaultInstance(), credential) .setApplicationName("Google-PlusSample/1.0") .build();
هویت موتور برنامه Google
این اعتبار جایگزین بر اساس Google App Engine App Identity Java API است. برخلاف اعتباری که در آن یک برنامه مشتری درخواست دسترسی به دادههای کاربر نهایی را میدهد، App Identity API دسترسی به دادههای خود برنامه مشتری را فراهم میکند.
از AppIdentityCredential (از google-api-client-appengine ) استفاده کنید. این اعتبار بسیار ساده تر است زیرا Google App Engine از تمام جزئیات مراقبت می کند. شما فقط محدوده OAuth 2.0 مورد نیاز خود را مشخص می کنید.
کد مثال گرفته شده از urlshortener-robots-appengine-sample :
static Urlshortener newUrlshortener() { AppIdentityCredential credential = new AppIdentityCredential( Collections.singletonList(UrlshortenerScopes.URLSHORTENER)); return new Urlshortener.Builder(new UrlFetchTransport(), GsonFactory.getDefaultInstance(), credential) .build(); }
ذخیره داده
تاریخ انقضای یک نشانه دسترسی معمولاً 1 ساعت است و پس از آن در صورت استفاده از آن با خطا مواجه می شوید. GoogleCredential از "بازسازی" خودکار توکن مراقبت می کند، که به سادگی به معنای دریافت رمز دسترسی جدید است. این کار با استفاده از یک نشانه تازهسازی طولانی مدت انجام میشود، که معمولاً در صورت استفاده از پارامتر access_type=offline
در طول جریان کد مجوز، همراه با رمز دسترسی دریافت میشود (به GoogleAuthorizationCodeFlow.Builder.setAccessType(String) مراجعه کنید).
بیشتر برنامهها باید رمز دسترسی اعتبارنامه و/یا نشانه تازهسازی را حفظ کنند. برای تداوم دسترسی به اعتبار و/یا بازخوانی توکنها، میتوانید پیادهسازی DataStoreFactory خود را با StoredCredential ارائه دهید. یا می توانید از یکی از پیاده سازی های زیر ارائه شده توسط کتابخانه استفاده کنید:
- AppEngineDataStoreFactory : اعتبار را با استفاده از Google App Engine Data Store API حفظ می کند.
- MemoryDataStoreFactory : اعتبارنامه را در حافظه "پاک می کند" که فقط به عنوان یک ذخیره سازی کوتاه مدت برای طول عمر فرآیند مفید است.
- FileDataStoreFactory : اعتبارنامه را در یک فایل حفظ می کند.
کاربران AppEngine: AppEngineCredentialStore منسوخ شده است و به زودی حذف خواهد شد. توصیه می کنیم از AppEngineDataStoreFactory با StoredCredential استفاده کنید. اگر اعتبارنامه هایی را به روش قدیمی ذخیره کرده اید، می توانید از روش های کمکی اضافه شده migrateTo(AppEngineDataStoreFactory) یا migrateTo(DataStore) برای انجام انتقال استفاده کنید.
میتوانید از DataStoreCredentialRefreshListener استفاده کنید و آن را برای اعتبار با استفاده از GoogleCredential.Builder.addRefreshListener (CredentialRefreshListener) تنظیم کنید.
جریان کد مجوز
از جریان کد مجوز استفاده کنید تا به کاربر نهایی اجازه دهید به برنامه شما اجازه دسترسی به داده های محافظت شده خود در APIهای Google را بدهد. پروتکل این جریان در مجوز کد Grant مشخص شده است.
این جریان با استفاده از GoogleAuthorizationCodeFlow پیاده سازی می شود. مراحل عبارتند از:
- کاربر نهایی به برنامه شما وارد می شود. شما باید آن کاربر را با یک شناسه کاربری که برای برنامه شما منحصر به فرد است مرتبط کنید.
- برای بررسی اینکه آیا اعتبار کاربر نهایی از قبل شناخته شده است یا خیر ، AuthorizationCodeFlow.loadCredential (String) ) را بر اساس شناسه کاربر فراخوانی کنید. اگر چنین است، کار ما تمام شده است.
- در غیر این صورت، با AuthorizationCodeFlow.newAuthorizationUrl() تماس بگیرید و مرورگر کاربر نهایی را به صفحه مجوز هدایت کنید تا به برنامه شما اجازه دسترسی به داده های محافظت شده خود را بدهد.
- سپس سرور مجوز Google مرورگر را به آدرس URL تغییر مسیر مشخص شده توسط برنامه شما همراه با یک پارامتر جستجوی
code
هدایت می کند. از پارامترcode
برای درخواست رمز دسترسی با استفاده از AuthorizationCodeFlow.newTokenRequest (String) استفاده کنید. - از AuthorizationCodeFlow.createAndStoreCredential(TokenResponse، String) ) برای ذخیره و دریافت اعتبار برای دسترسی به منابع محافظت شده استفاده کنید.
از طرف دیگر، اگر از GoogleAuthorizationCodeFlow استفاده نمی کنید، می توانید از کلاس های سطح پایین تر استفاده کنید:
- از DataStore.get(String) برای بارگیری اعتبار از فروشگاه بر اساس شناسه کاربر استفاده کنید.
- از GoogleAuthorizationCodeRequestUrl برای هدایت مرورگر به صفحه مجوز استفاده کنید.
- از AuthorizationCodeResponseUrl برای پردازش پاسخ مجوز و تجزیه کد مجوز استفاده کنید.
- از GoogleAuthorizationCodeTokenRequest برای درخواست یک نشانه دسترسی و احتمالاً یک نشانه بازخوانی استفاده کنید.
- یک GoogleCredential جدید ایجاد کنید و آن را با استفاده از DataStore.set (String, V) ذخیره کنید.
- با استفاده از
GoogleCredential
به منابع محافظت شده دسترسی پیدا کنید. نشانههای دسترسی منقضی شده بهطور خودکار با استفاده از نشانه تازهسازی (در صورت وجود) بازخوانی میشوند. مطمئن شوید که از DataStoreCredentialRefreshListener استفاده کرده و آن را برای اعتبار با استفاده از GoogleCredential.Builder.addRefreshListener(CredentialRefreshListener) تنظیم کنید.
وقتی پروژه خود را در Google API Console راهاندازی میکنید، بسته به جریانی که استفاده میکنید، اعتبارنامههای مختلف را انتخاب میکنید. برای جزئیات بیشتر، به تنظیم سناریوهای OAuth 2.0 و OAuth 2.0 مراجعه کنید. قطعه کد برای هر یک از جریان ها در زیر آمده است.
برنامه های کاربردی وب سرور
پروتکل این جریان در Using OAuth 2.0 for Web Server Applications توضیح داده شده است.
این کتابخانه کلاس های کمکی servlet را برای ساده کردن قابل توجه جریان کد مجوز برای موارد استفاده اساسی ارائه می دهد. شما فقط زیر کلاس های مشخص AbstractAuthorizationCodeServlet و AbstractAuthorizationCodeCallbackServlet (از google-oauth-client-servlet ) را ارائه کرده و آنها را به فایل web.xml خود اضافه کنید. توجه داشته باشید که هنوز باید مراقب ورود کاربر برای برنامه وب خود باشید و شناسه کاربری را استخراج کنید.
public class CalendarServletSample extends AbstractAuthorizationCodeServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { // do stuff } @Override protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException { GenericUrl url = new GenericUrl(req.getRequestURL().toString()); url.setRawPath("/oauth2callback"); return url.build(); } @Override protected AuthorizationCodeFlow initializeFlow() throws IOException { return new GoogleAuthorizationCodeFlow.Builder( new NetHttpTransport(), GsonFactory.getDefaultInstance(), "[[ENTER YOUR CLIENT ID]]", "[[ENTER YOUR CLIENT SECRET]]", Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory( DATA_STORE_FACTORY).setAccessType("offline").build(); } @Override protected String getUserId(HttpServletRequest req) throws ServletException, IOException { // return user ID } } public class CalendarServletCallbackSample extends AbstractAuthorizationCodeCallbackServlet { @Override protected void onSuccess(HttpServletRequest req, HttpServletResponse resp, Credential credential) throws ServletException, IOException { resp.sendRedirect("/"); } @Override protected void onError( HttpServletRequest req, HttpServletResponse resp, AuthorizationCodeResponseUrl errorResponse) throws ServletException, IOException { // handle error } @Override protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException { GenericUrl url = new GenericUrl(req.getRequestURL().toString()); url.setRawPath("/oauth2callback"); return url.build(); } @Override protected AuthorizationCodeFlow initializeFlow() throws IOException { return new GoogleAuthorizationCodeFlow.Builder( new NetHttpTransport(), GsonFactory.getDefaultInstance() "[[ENTER YOUR CLIENT ID]]", "[[ENTER YOUR CLIENT SECRET]]", Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory( DATA_STORE_FACTORY).setAccessType("offline").build(); } @Override protected String getUserId(HttpServletRequest req) throws ServletException, IOException { // return user ID } }
برنامه های کاربردی Google App Engine
جریان کد مجوز در App Engine تقریباً مشابه جریان کد مجوز سرورلت است، با این تفاوت که ما میتوانیم از API جاوا کاربران Google App Engine استفاده کنیم. کاربر باید وارد سیستم شود تا Users Java API فعال شود. برای اطلاعات در مورد هدایت مجدد کاربران به صفحه ورود به سیستم در صورتی که قبلاً وارد سیستم نشدهاند، به امنیت و احراز هویت (در web.xml) مراجعه کنید.
تفاوت اصلی در مورد Servlet در این است که شما زیر کلاسهای بتونی از AbstractAppengineauthorizationCodeServlet و AbstractAppengineAuthorizationCodeCallbackservlet (از Google -Oauuth-Client-Appengine . آنها کلاسهای سرویس انتزاعی را گسترش می دهند و روش getUserId
برای شما با استفاده از کاربران Java Api. Appengineatoreforefordate (Appenginefinefinefationatorefectorefectorefectorefectoreforce (Appenginefinefationate) ارائه می دهند. -http-client-appengine ) گزینه خوبی برای حفظ اعتبار با استفاده از Google App Engine Data Store API است.
مثال گرفته شده (کمی تغییر یافته) از calendar-appengine-sample :
public class CalendarAppEngineSample extends AbstractAppEngineAuthorizationCodeServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { // do stuff } @Override protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException { return Utils.getRedirectUri(req); } @Override protected AuthorizationCodeFlow initializeFlow() throws IOException { return Utils.newFlow(); } } class Utils { static String getRedirectUri(HttpServletRequest req) { GenericUrl url = new GenericUrl(req.getRequestURL().toString()); url.setRawPath("/oauth2callback"); return url.build(); } static GoogleAuthorizationCodeFlow newFlow() throws IOException { return new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, getClientCredential(), Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory( DATA_STORE_FACTORY).setAccessType("offline").build(); } } public class OAuth2Callback extends AbstractAppEngineAuthorizationCodeCallbackServlet { private static final long serialVersionUID = 1L; @Override protected void onSuccess(HttpServletRequest req, HttpServletResponse resp, Credential credential) throws ServletException, IOException { resp.sendRedirect("/"); } @Override protected void onError( HttpServletRequest req, HttpServletResponse resp, AuthorizationCodeResponseUrl errorResponse) throws ServletException, IOException { String nickname = UserServiceFactory.getUserService().getCurrentUser().getNickname(); resp.getWriter().print("<h3>" + nickname + ", why don't you want to play with me?</h1>"); resp.setStatus(200); resp.addHeader("Content-Type", "text/html"); } @Override protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException { return Utils.getRedirectUri(req); } @Override protected AuthorizationCodeFlow initializeFlow() throws IOException { return Utils.newFlow(); } }
برای نمونه اضافی، storage-serviceaccount-appengine-sample را ببینید.
حساب های خدماتی
GoogleCredential از حسابهای سرویس نیز پشتیبانی میکند. برخلاف اعتباری که در آن یک برنامه مشتری درخواست دسترسی به دادههای کاربر نهایی را میدهد، حسابهای خدمات دسترسی به دادههای خود برنامه مشتری را فراهم میکنند. برنامه مشتری شما با استفاده از کلید خصوصی دانلود شده از Google API Console، درخواست یک نشانه دسترسی را امضا می کند.
کد مثال گرفته شده از plus-serviceaccount-cmdline-sample :
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport(); JsonFactory jsonFactory = GsonFactory.getDefaultInstance(); ... // Build service account credential. GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json")) .createScoped(Collections.singleton(PlusScopes.PLUS_ME)); // Set up global Plus instance. plus = new Plus.Builder(httpTransport, jsonFactory, credential) .setApplicationName(APPLICATION_NAME).build(); ...
برای نمونه اضافی، storage-serviceaccount-cmdline-sample را ببینید.
جعل هویت
همچنین میتوانید از جریان حساب سرویس برای جعل هویت کاربر در دامنهای که مالک آن هستید استفاده کنید. این بسیار شبیه به جریان حساب سرویس در بالا است، اما شما همچنین GoogleCredential.Builder.setServiceAccountUser(String) را فراخوانی می کنید.
برنامه های نصب شده
این جریان کد مجوز خط فرمان است که در استفاده از OAuth 2.0 برای برنامه های نصب شده توضیح داده شده است.
قطعه نمونه از plus-cmdline-sample :
public static void main(String[] args) { try { httpTransport = GoogleNetHttpTransport.newTrustedTransport(); dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR); // authorization Credential credential = authorize(); // set up global Plus instance plus = new Plus.Builder(httpTransport, JSON_FACTORY, credential).setApplicationName( APPLICATION_NAME).build(); // ... } private static Credential authorize() throws Exception { // load client secrets GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(PlusSample.class.getResourceAsStream("/client_secrets.json"))); // set up authorization code flow GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder( httpTransport, JSON_FACTORY, clientSecrets, Collections.singleton(PlusScopes.PLUS_ME)).setDataStoreFactory( dataStoreFactory).build(); // authorize return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user"); }
برنامه های کاربردی سمت مشتری
برای استفاده از جریان مشتری مبتنی بر مرورگر که در استفاده از OAuth 2.0 برای برنامههای سمت کلاینت توضیح داده شده است، معمولاً این مراحل را دنبال میکنید:
- کاربر نهایی در مرورگر را با استفاده از GoogleBrowserClientRequestUrl به صفحه مجوز هدایت کنید تا برنامه مرورگر شما به داده های محافظت شده کاربر نهایی دسترسی پیدا کند.
- از Google API Client Library برای جاوا اسکریپت برای پردازش نشانه دسترسی یافت شده در قطعه URL در URI تغییر مسیر ثبت شده در Google API Console استفاده کنید.
نمونه استفاده برای یک برنامه وب:
public void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException { String url = new GoogleBrowserClientRequestUrl("812741506391.apps.googleusercontent.com", "https://oauth2.example.com/oauthcallback", Arrays.asList( "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile")).setState("/profile").build(); response.sendRedirect(url); }
اندروید
از کدام کتابخانه با اندروید استفاده شود:
اگر در حال توسعه برای Android هستید و Google API که میخواهید استفاده کنید در کتابخانه خدمات Google Play گنجانده شده است، از آن کتابخانه برای بهترین عملکرد و تجربه استفاده کنید. اگر Google API که میخواهید با Android استفاده کنید بخشی از کتابخانه خدمات Google Play نیست، میتوانید از Google API Client Library برای جاوا استفاده کنید که از Android 4.0 (Ice Cream Sandwich) (یا بالاتر) پشتیبانی میکند و در اینجا توضیح داده شده است. . پشتیبانی از Android در Google API Client Library برای جاوا @Beta است.
پس زمینه:
با شروع Eclair (SDK 2.1)، حسابهای کاربری در دستگاه Android با استفاده از مدیریت حساب مدیریت میشوند. تمام مجوزهای برنامه Android به طور مرکزی توسط SDK با استفاده از AccountManager مدیریت می شود. شما محدوده OAuth 2.0 مورد نیاز برنامه خود را مشخص می کنید، و یک رمز دسترسی برای استفاده برمی گرداند.
محدوده OAuth 2.0 از طریق پارامتر authTokenType
به عنوان oauth2:
به اضافه دامنه مشخص می شود. به عنوان مثال:
oauth2:https://www.googleapis.com/auth/tasks
این دسترسی خواندن/نوشتن به Google Tasks API را مشخص می کند. اگر به چندین محدوده OAuth 2.0 نیاز دارید، از یک لیست جدا شده با فاصله استفاده کنید.
برخی از API ها دارای پارامترهای authTokenType
خاصی هستند که کار می کنند. به عنوان مثال، "Manage your tasks" نام مستعار برای مثال authtokenType
است که در بالا نشان داده شده است.
همچنین باید کلید API را از Google API Console مشخص کنید. در غیر این صورت، توکنی که AccountManager به شما می دهد فقط سهمیه ناشناس را در اختیار شما قرار می دهد که معمولاً بسیار کم است. در مقابل، با تعیین یک کلید API، سهمیه رایگان بیشتری دریافت میکنید و میتوانید به صورت اختیاری صورتحساب را برای استفاده بالاتر از آن تنظیم کنید.
نمونه کد کد گرفته شده از tasks-android-sample :
com.google.api.services.tasks.Tasks service; @Override public void onCreate(Bundle savedInstanceState) { credential = GoogleAccountCredential.usingOAuth2(this, Collections.singleton(TasksScopes.TASKS)); SharedPreferences settings = getPreferences(Context.MODE_PRIVATE); credential.setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, null)); service = new com.google.api.services.tasks.Tasks.Builder(httpTransport, jsonFactory, credential) .setApplicationName("Google-TasksAndroidSample/1.0").build(); } private void chooseAccount() { startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case REQUEST_GOOGLE_PLAY_SERVICES: if (resultCode == Activity.RESULT_OK) { haveGooglePlayServices(); } else { checkGooglePlayServicesAvailable(); } break; case REQUEST_AUTHORIZATION: if (resultCode == Activity.RESULT_OK) { AsyncLoadTasks.run(this); } else { chooseAccount(); } break; case REQUEST_ACCOUNT_PICKER: if (resultCode == Activity.RESULT_OK && data != null && data.getExtras() != null) { String accountName = data.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME); if (accountName != null) { credential.setSelectedAccountName(accountName); SharedPreferences settings = getPreferences(Context.MODE_PRIVATE); SharedPreferences.Editor editor = settings.edit(); editor.putString(PREF_ACCOUNT_NAME, accountName); editor.commit(); AsyncLoadTasks.run(this); } } break; } }