Genel Bakış
Amaç: Bu belgede, Google Cloud Search tarafından sunulan genel OAuth 2.0 işlevleri Google OAuth İstemci Kitaplığı. Bu işlevleri şunlar için kullanabilirsiniz: İnternet hizmetleri için kimlik doğrulaması ve yetkilendirme.
GoogleCredential
kullanarak OAuth 2.0 yetkilendirmesi gerçekleştirmek için talimatlar:
Google hizmetleri (bkz.
Java için Google API istemci kitaplığı ile OAuth 2.0'ı kullanma.
Özet: OAuth 2.0, Google tarafından Son kullanıcıların bir istemciyi güvenli bir şekilde yetkilendirmesine izin veren standart spesifikasyon korumasındaki sunucu tarafı kaynaklara erişmek için kullanır. Ayrıca, OAuth 2.0 hamiline ait jeton spesifikasyonu, bir erişim kodu kullanarak bu korunan kaynaklara nasıl erişileceğini son kullanıcı yetkilendirme işlemi sırasında verildi.
Ayrıntılı bilgi için aşağıdaki paketlere ilişkin Javadoc dokümanlarına bakın:
- com.google.api.client.auth.oauth2 (google-oauth-client parametresinden)
- com.google.api.client.extensions.servlet.auth.oauth2 (from google-oauth-client-servlet)
- com.google.api.client.extensions.appengine.auth.oauth2 (from google-oauth-client-appengine)
Müşteri kaydı
Java için Google OAuth İstemci Kitaplığı'nı kullanmadan önce büyük olasılıkla almak için uygulamanızı bir yetkilendirme sunucusuna kaydetme ve istemci sırrı: (Bu işlem hakkında genel bilgi için bkz. Müşteri Kayıt spesifikasyonu.)
Kimlik bilgisi ve kimlik bilgisi deposu
Kimlik bilgisi
korumalı kaynaklara erişmek için kullanılan iş parçacığı açısından güvenli bir OAuth 2.0 yardımcı sınıfıdır.
erişim jetonu. Yenileme jetonu kullanılırken Credential
, erişimi de yeniler
yenileme jetonunu kullanarak erişim jetonunun süresi dolmadan yeni bir jeton oluşturun. Örneğin,
zaten bir erişim jetonunuz varsa aşağıdaki şekilde istekte bulunabilirsiniz:
public static HttpResponse executeGet( HttpTransport transport, JsonFactory jsonFactory, String accessToken, GenericUrl url) throws IOException { Credential credential = new Credential(BearerToken.authorizationHeaderAccessMethod()).setAccessToken(accessToken); HttpRequestFactory requestFactory = transport.createRequestFactory(credential); return requestFactory.buildGetRequest(url).execute(); }
Çoğu uygulamanın, kimlik bilgilerinin erişim jetonunu sürdürmesi ve yetkilendirmeye gelecekte yeniden yönlendirme yapmamak için jetonu yenileme sayfasını ziyaret ederek kontrol edebilirsiniz. İlgili içeriği oluşturmak için kullanılan CredentialStore bu kitaplıktaki uygulama desteği sonlandırıldı ve bu uygulama ileride kaldırılacaktır yayınlar. Alternatif olarak, DataStoreFactory ve DataStore şununla arayüz: StoredCredential, tarafından sağlanan Java için Google HTTP istemci kitaplığı.
Kitaplık tarafından sağlanan aşağıdaki uygulamalardan birini kullanabilirsiniz:
- JdoDataStoreFactory kimlik bilgisini JDO kullanarak korur.
- AppEngineDataStoreFactory Google App Engine Data Store API'yi kullanarak kimlik bilgisini güncel tutmalıdır.
- MemoryDataStoreFactory "kalıcı" Bu, yalnızca kısa vadeli kullanım ve proje başlatma belgesi bir depolama alanına sahip olmanız gerekir.
- FileDataStoreFactory kimlik bilgisini bir dosyada tutar.
Google App Engine kullanıcıları:
AppEngineCredentialStore kullanımdan kaldırıldı ve artık kaldırılıyor.
Optimum kampanya performansı için AppEngineDataStoreFactory StoredCredential ile kullanın. Eski yöntemle depolanmış kimlik bilgileriniz varsa ek yardımcı yöntemleri kullanabilirsiniz migrateTo(AppEngineDataStoreFactory) veya migrateTo(DataStore) tıklayın.
DataStoreCredentialRefreshListener'ı kullanın. ve bunu kullanarak kimlik bilgisi için GoogleCredential.Builder.addRefreshListener(CredentialRefreshListener).
Yetkilendirme kodu akışı
Son kullanıcının uygulamanıza izin vermesi için yetkilendirme kodu akışını kullanın tarafından korunuyor. Bu akışa ilişkin protokol Yetkilendirme Kodu İzni spesifikasyonu.
Bu akış, AuthorizationCodeFlow. Adımlar aşağıdaki gibidr:
- Bir son kullanıcı uygulamanıza giriş yapar. Bu kullanıcıyı uygulamanız için benzersiz bir kullanıcı kimliği belirtir.
- Telefonla arama AuthorizationCodeFlow.loadCredential(String), kullanıcının kimlik bilgilerinin zaten bilinip bilinmediğini kontrol etmek için kullanıcı kimliğini temel alır. Öyleyse, işleminiz tamamlanmıştır.
- Aksi halde AuthorizationCodeFlow.newAuthorizationUrl() çağrısını yapın ve son kullanıcının tarayıcısını, bir web sitesini ziyaret eden uygulamanızın korunan verilerine erişmesine izin vermez.
- Daha sonra web tarayıcısı, bir "kod" ile yönlendirme URL'sine yönlendirir sorgu Bu parametre, daha sonra AuthorizationCodeFlow.newTokenRequest(String) kullanma
- Tekliflerinizi otomatikleştirmek ve optimize etmek için AuthorizationCodeFlow.createAndStoreCredential(TokenResponse, String) (korunan kaynaklara erişmek için kimlik bilgisi depolamak ve almak için)
Alternatif olarak AuthorizationCodeFlow, daha alt düzey sınıfları kullanabilirsiniz:
- DataStore.get(String) yöntemini kullanın seçeneğini kullanın.
- AuthorizationCodeRequestUrl'yi kullanma tıklayın.
- AuthorizationCodeResponseUrl kullanma özelliğini kullanmanız gerekir.
- AuthorizationCodeTokenRequest kullanma bir erişim jetonu ve muhtemelen bir yenileme jetonu istemesi gerekir.
- Yeni bir Kimlik Bilgisi oluşturun ve DataStore.set(String, V) yöntemini kullanarak saklayın.
- Kimlik bilgisini kullanarak korunan kaynaklara erişin. Süresi dolan erişim jetonları aşağıdaki durumlarda yenileme jetonu kullanılarak otomatik olarak yenilenir: geçerlidir. Şunu kullandığınıza emin olun: DataStoreCredentialRefreshListener ve bunu kullanarak kimlik bilgisi için Credential.Builder.addRefreshListener(CredentialRefreshListener).
Servlet yetkilendirme kodu akışı
Bu kitaplık, performansı önemli ölçüde basitleştirmek için servlet yardımcı sınıfları yetkilendirme kodu akışını izleyin. Yalnızca somut alt sınıflar sağlarsınız / AbstractAuthorizationCodeServlet ve AbstractAuthorizationCodeCallbackServlet (google-oauth-client-servlet'ten) ve web.xml dosyanıza ekleyin. Kullanıcıyla yine de ilgilenmeniz gerektiğini unutmayın. web uygulamanız için giriş yapın ve bir kullanıcı kimliği çıkarın.
Örnek kod:
public class ServletSample 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 AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(), new NetHttpTransport(), new JacksonFactory(), new GenericUrl("https://server.example.com/token"), new BasicAuthentication("s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw"), "s6BhdRkqt3", "https://server.example.com/authorize").setCredentialDataStore( StoredCredential.getDefaultDataStore( new FileDataStoreFactory(new File("datastoredir")))) .build(); } @Override protected String getUserId(HttpServletRequest req) throws ServletException, IOException { // return user ID } } public class ServletCallbackSample 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 AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(), new NetHttpTransport(), new JacksonFactory(), new GenericUrl("https://server.example.com/token"), new BasicAuthentication("s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw"), "s6BhdRkqt3", "https://server.example.com/authorize").setCredentialDataStore( StoredCredential.getDefaultDataStore( new FileDataStoreFactory(new File("datastoredir")))) .build(); } @Override protected String getUserId(HttpServletRequest req) throws ServletException, IOException { // return user ID } }
Google App Engine yetkilendirme kodu akışı
App Engine'deki yetkilendirme kodu akışı servlet ile neredeyse aynıdır yetkilendirme kodu akışını, yalnızca Google App Engine'in Kullanıcılar Java API'si. Users Java API'nin etkinleştirilmesi için kullanıcının giriş yapmış olması gerekir; şunun için: halihazırda değilse, kullanıcıları bir giriş sayfasına yönlendirmeyle ilgili bilgiler giriş yaptınız, bkz. Güvenlik ve Kimlik Doğrulama (web.xml dosyasında).
servlet durumundan ilk fark, somut bir ortam sağlayarak
alt sınıfları
AbstractAppEngineAuthorizationCodeServlet ve AbstractAppEngineAuthorizationCodeCallbackServlet (google-oauth-client-appengine'den). Soyut servlet sınıflarını genişletir ve Users Java API'yi kullanarak getUserId
yöntemini sizin için uygular. AppEngineDataStoreFactory (Java için Google HTTP İstemci Kitaplığı'ndan), Google App Engine Data Store API'yi kullanarak kimlik bilgisini kalıcı hale getirmek için iyi bir seçenektir.
Örnek kod:
public class AppEngineSample extends AbstractAppEngineAuthorizationCodeServlet { @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 AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(), new UrlFetchTransport(), new JacksonFactory(), new GenericUrl("https://server.example.com/token"), new BasicAuthentication("s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw"), "s6BhdRkqt3", "https://server.example.com/authorize").setCredentialStore( StoredCredential.getDefaultDataStore(AppEngineDataStoreFactory.getDefaultInstance())) .build(); } } public class AppEngineCallbackSample extends AbstractAppEngineAuthorizationCodeCallbackServlet { @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 AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(), new UrlFetchTransport(), new JacksonFactory(), new GenericUrl("https://server.example.com/token"), new BasicAuthentication("s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw"), "s6BhdRkqt3", "https://server.example.com/authorize").setCredentialStore( StoredCredential.getDefaultDataStore(AppEngineDataStoreFactory.getDefaultInstance())) .build(); } }
Komut satırı yetkilendirme kod akışı
Şuradan alınan basitleştirilmiş örnek kod: dailymotion-cmdline-sample:
/** Authorizes the installed application to access user's protected data. */ private static Credential authorize() throws Exception { OAuth2ClientCredentials.errorIfNotSpecified(); // set up authorization code flow AuthorizationCodeFlow flow = new AuthorizationCodeFlow.Builder(BearerToken .authorizationHeaderAccessMethod(), HTTP_TRANSPORT, JSON_FACTORY, new GenericUrl(TOKEN_SERVER_URL), new ClientParametersAuthentication( OAuth2ClientCredentials.API_KEY, OAuth2ClientCredentials.API_SECRET), OAuth2ClientCredentials.API_KEY, AUTHORIZATION_SERVER_URL).setScopes(Arrays.asList(SCOPE)) .setDataStoreFactory(DATA_STORE_FACTORY).build(); // authorize LocalServerReceiver receiver = new LocalServerReceiver.Builder().setHost( OAuth2ClientCredentials.DOMAIN).setPort(OAuth2ClientCredentials.PORT).build(); return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user"); } private static void run(HttpRequestFactory requestFactory) throws IOException { DailyMotionUrl url = new DailyMotionUrl("https://api.dailymotion.com/videos/favorites"); url.setFields("id,tags,title,url"); HttpRequest request = requestFactory.buildGetRequest(url); VideoFeed videoFeed = request.execute().parseAs(VideoFeed.class); ... } public static void main(String[] args) { ... DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR); final Credential credential = authorize(); HttpRequestFactory requestFactory = HTTP_TRANSPORT.createRequestFactory(new HttpRequestInitializer() { @Override public void initialize(HttpRequest request) throws IOException { credential.initialize(request); request.setParser(new JsonObjectParser(JSON_FACTORY)); } }); run(requestFactory); ... }
Tarayıcı tabanlı istemci akışı
Bunlar, Dolaylı Hibe spesifikasyonu:
- BrowserClientRequestUrl'ni kullanarak son kullanıcının tarayıcısını, kullanıcının uygulamanızın korunan verilerine erişmesine izin verebilirsiniz.
- URL'de bulunan erişim jetonunu işlemek için bir JavaScript uygulaması kullanın parçası, yetkilendirme sunucusuna kayıtlı yönlendirme URI'sındaki
Bir web uygulaması için örnek kullanım:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { String url = new BrowserClientRequestUrl( "https://server.example.com/authorize", "s6BhdRkqt3").setState("xyz") .setRedirectUri("https://client.example.com/cb").build(); response.sendRedirect(url); }
Süresi dolmuş bir erişim jetonunu algılama
OAuth 2.0 taşıyıcı spesifikasyonuna göre,
sunucu, erişimi süresi dolmuş korumalı bir kaynağa erişmek için çağrıldığında
belirtilmezse sunucu genellikle bir HTTP 401 Unauthorized
durum koduyla
Örneğin:
HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer realm="example", error="invalid_token", error_description="The access token expired"
Ancak spesifikasyonda oldukça fazla esneklik olduğu görülüyor. Örneğin, OAuth 2.0 sağlayıcısının dokümanlarına bakın.
Alternatif bir yaklaşım, expires_in
parametresini
erişim jetonu yanıtı.
Bu değer, verilen erişim jetonunun saniye cinsinden ömrünü belirtir.
genellikle bir saat sürer. Ancak erişim jetonunun süresi sonunda dolmamış olabilir
çok daha fazla zaman alabilir. Sunucu, erişim izni vermeye devam edebilir. İşte bu yüzden
genellikle bunun yerine bir 401 Unauthorized
durum kodu beklemenizi önerir.
geçen süreye göre jetonun süresinin dolduğu varsayılmıştır. Alternatif olarak
süresi dolmadan kısa süre önce bir erişim jetonunu yenilemeyi deneyin ve jeton sunucusu
kullanılamıyor, 401
alana kadar erişim jetonunu kullanmaya devam edin. Bu
proje yönetiminde varsayılan olarak
Kimlik bilgisi.
Diğer bir seçenek de her istekten önce yeni bir erişim jetonu almaktır. her seferinde jeton sunucusuna fazladan bir HTTP isteği gerektirir. Bu nedenle hız ve ağ kullanımı açısından kötü bir seçim. İdeal olarak, erişim jetonunu uygulamaların yeni erişim isteklerini en aza indirmek için güvenli, kalıcı depolama alanında jeton. (Ancak yüklü uygulamalar için güvenli depolama, zor bir sorundur.)
Erişim jetonunun, geçerlilik süresinin dolmasından farklı nedenlerle geçersiz hale gelebileceğini Örneğin, kullanıcı jetonu açık bir şekilde iptal ettiyse nasıl güvenilir bir kod olduğuna dikkat çekmek istiyorum. Bir jetonun artık kullanılamadığını tespit ettiğinizde geçerlidir. Örneğin, süresi dolmuş veya iptal edilmişse erişim iznini kaldırmalısınız. jeton. Örneğin, Android'de AccountManager.invalidateAuthToken.