RESTful web servisi - diğer servislerden gelen talepleri nasıl doğrularsınız?


117

Kullanıcıların yanı sıra diğer web hizmetleri ve uygulamaları tarafından erişilmesi gereken bir RESTful web hizmeti tasarlıyorum. Gelen tüm isteklerin doğrulanması gerekir. Tüm iletişim HTTPS üzerinden gerçekleşir. Kullanıcı kimlik doğrulaması, kullanıcı adı ve parolanın (bir SSL bağlantısı üzerinden) hizmet tarafından sağlanan bir / session kaynağına POST ile alınmasıyla elde edilen bir kimlik doğrulama belirtecine dayalı olarak çalışacaktır .

Web hizmeti istemcileri söz konusu olduğunda , istemci hizmetinin arkasında son kullanıcı yoktur . İstekler, planlanan görevler, olaylar veya diğer bazı bilgisayar işlemleri tarafından başlatılır. Bağlantı hizmetlerinin listesi önceden bilinmektedir (tabii ki, sanırım). Diğer (web) hizmetlerinden gelen bu istekleri nasıl doğrulamalıyım? Kimlik doğrulama sürecinin bu hizmetler için mümkün olduğunca kolay uygulanmasını, ancak güvenlik pahasına olmamasını istiyorum. Böyle bir senaryo için standart ve en iyi uygulamalar nelerdir?

Aklıma gelen (veya bana önerilmiş) seçenekler:

  1. İstemci hizmetlerinin "sahte" bir kullanıcı adı ve parolaya başvurmasını sağlayın ve kullanıcılarla aynı şekilde kimliklerini doğrulayın. Bu seçeneği sevmiyorum - sadece doğru hissettirmiyor.

  2. İstemci hizmeti için kalıcı bir uygulama kimliği, muhtemelen bir uygulama anahtarı da atayın. Anladığım kadarıyla bu, kullanıcı adı + şifreye sahip olmakla aynı şey. Bu kimlik ve anahtarla, her isteğin kimliğini doğrulayabilir veya diğer istekleri doğrulamak için bir kimlik doğrulama simgesi oluşturabilirim. Her iki durumda da, bu seçeneği sevmiyorum, çünkü uygulama kimliğini ve anahtarını ele geçirebilen herkes istemciyi taklit edebilir.

  3. Önceki seçeneğe bir IP adresi kontrolü ekleyebilirim. Bu, sahte isteklerin gerçekleştirilmesini zorlaştırır.

  4. İstemci sertifikaları. Kendi sertifika yetkilimi kur, kök sertifika oluştur ve istemci hizmetleri için istemci sertifikaları oluştur. Yine de birkaç sorun akla geliyor: a) Kullanıcıların sertifikalar olmadan kimlik doğrulamasına nasıl izin veriyorum ve b) bu ​​senaryonun istemci hizmeti açısından uygulanması ne kadar karmaşık?

  5. Başka bir şey - orada başka çözümler olmalı?

Hizmetim Java üzerinde çalışıyor olacaktı, ancak hangi özel çerçevenin üzerine inşa edileceğiyle ilgili bilgileri kasıtlı olarak dışarıda bıraktım, çünkü temel ilkelerle daha çok ilgileniyorum ve uygulama ayrıntılarıyla çok fazla ilgilenmiyorum - Bunun için en iyi çözümü varsayıyorum temel çerçeveden bağımsız olarak uygulanması mümkün olacaktır. Bununla birlikte, bu konuda biraz deneyimsizim, bu nedenle gerçek uygulama hakkında somut ipuçları ve örnekler (yararlı üçüncü taraf kitaplıkları, makaleler, vb.) Da çok takdir edilecektir.


Önerebilirsem, büyük web sitesi hizmetlerine aşina olun ve neyi beğendiğinizi seçin ve seçin. Kullanıcılarınız ayrıca diğer RESTful hizmetlerinin en iyi uygulamalarıyla benzerlikler bulacaktır.
Yzmir Ramirez

Benzer bir konuya değinen başka bir soru (neredeyse iki yaşında) bulundu: stackoverflow.com/questions/1138831/…
Tommi

Hizmetler (hem web hem de diğerleri) hangi işletim sisteminde barındırılıyor? Aynı altyapının parçası olan sunucularda mı çalışıyorlar?
Anders Abel

İşletim sistemi değişebilir: Win, * nix vb. Ve istemci hizmetleri, hizmetimle aynı altyapı içinde olabilir veya olmayabilir.
Tommi

Yanıtlar:


34

Bu soruna yönelik herhangi bir çözüm, paylaşılan bir sırra indirgeniyor. Sabit kodlu kullanıcı adı ve şifre seçeneğini de sevmiyorum ama oldukça basit olmasının faydası var. İstemci sertifikası da iyi ama gerçekten çok farklı mı? Sunucuda ve istemcide bir sertifika var. Ana avantajı, kaba kuvvet kullanmanın daha zor olmasıdır. Umarım buna karşı korunmak için başka korumalarınız vardır.

İstemci sertifikası çözümü için A noktanızın çözülmesinin zor olduğunu sanmıyorum. Sadece bir dal kullanıyorsun. if (client side certificat) { check it } else { http basic auth }Java uzmanı değilim ve istemci tarafı sertifikaları yapmak için onunla hiç çalışmadım. Ancak hızlı bir Google bizi sokağınıza bakan bu eğiticiye götürür .

Tüm bu "en iyisi" tartışmasına rağmen, "daha az kod, daha az akıllılık daha iyidir" diyen başka bir felsefe olduğunu belirtmeme izin verin. (Bu felsefeye şahsen sahibim). İstemci sertifika çözümü kulağa çok fazla kod gibi geliyor.

OAuth ile ilgili soru sorduğunuzu biliyorum, ancak OAuth2 önerisi, SSL ile birlikte kullanılması gereken " taşıyıcı jetonlar " adlı sorununuza bir çözüm içeriyor . Bence, basitlik uğruna, ya sabit kodlanmış kullanıcı / geçişi (uygulama başına bir tane, böylece tek tek iptal edilebilirler) ya da çok benzer taşıyıcı belirteçlerini seçerdim.


27
İstemci sertifikaları paylaşılan bir sır DEĞİLDİR. Bu yüzden varlar. İstemcinin özel bir anahtarı vardır ve sunucunun bir genel anahtarı vardır. Müşteri sırrını asla paylaşmaz ve açık anahtar bir sır değildir.
Tim

5
Öğretici bağlantısı bir eğitim makalesine değil Oracle sitesindeki bazı Java dizin sayfasına yönlendiriyor ...
Marjan Venema

2
@MarjanVenema Eh, çünkü newz2000'i yanıtladıktan +2 yıl sonra bağlantıyı deniyorsunuz, ancak her zaman WayBack
Fábio Duque Silva

1
@MarjanVenema: Üzgünüm ama newz2000'in buraya gelip bağlantı kesildikten sonra güncellemesini mi bekliyorsunuz? Dediğin gibi, bağlantı çürüyor, bu yüzden er ya da geç oluyor. Ya yazarın o sırada ne gördüğünü görmek için arşive erişmeye çalışırsınız ya da yeni bağlantıyı bulup olumlu bir katkıda bulunursunuz. Yorumunuzun kimseye nasıl yardımcı olduğunu anlamıyorum. Ama burada, şu bağlantıyı takip edin: oracle.com/technetwork/articles/javase/… (sonunda çürümesine dikkat edin)
Fábio Duque Silva

2
@ FábioSilva: Hayır. Bunu yapmasını beklemiyorum . Arşivi okudum ama yeni bir bağlantı aramaya zamanım olmadı, bu yüzden en iyi ikinci şeyi yaptım: topluluktan başka birinin yeni konumu bulup güncelleyebilmesi için öldüğüne dair bir yorum yazdım. İleti. Belli ki yeni bağlantıyı bulmak için vaktiniz olduğuna göre, beni meraklandıran bir yoruma koymak yerine gönderideki bağlantıyı neden güncellemediniz?
Marjan Venema

36

Sorunuzu okuduktan sonra, talepte bulunmak için özel bir belirteç oluşturmanızı söyleyebilirim. Bu jeton belirli bir zamanda yaşayacak (bir gün içinde diyelim).

İşte kimlik doğrulama belirteci oluşturmak için bir örnek:

(day * 10) + (month * 100) + (year (last 2 digits) * 1000)

örneğin: 3 Haziran 2011

(3 * 10) + (6 * 100) + (11 * 1000) = 
30 + 600 + 11000 = 11630

daha sonra kullanıcı şifresiyle birleştirin, örneğin "my4wesomeP4ssword!"

11630my4wesomeP4ssword!

Ardından bu dizenin MD5'ini yapın:

05a9d022d621b64096160683f3afe804

Ne zaman bir istek ararsınız, her zaman bu jetonu kullanın,

https://mywebservice.com/?token=05a9d022d621b64096160683f3afe804&op=getdata

Bu simge her zaman benzersizdir, bu nedenle bu tür bir korumanın hizmetinizi her zaman korumak için fazlasıyla yeterli olduğunu tahmin ediyorum.

Umut yardımcı olur

:)


1
Her istekte güvenlik belirtecini ekleme şeklinizi gerçekten seviyorum, ancak programcı zaten 100'lerce jsp sayfası oluşturduğunda ve bundan sonra t0 güvenliği önceden oluşturulmuş 100 sayfalara ve oluşturulacak sayfalara uyguladığında buna ne oluyor? Bu durumda her talebe jeton eklemek doğru bir seçim değildir.Her neyse tekniğiniz için +1. :)
Ankur Verma

4
Saatler senkronize edilmezse ne olur? Müşteri bu durumda yanlış jeton oluşturmaz mı? Her ikisi de UTC'de tarih saatini oluştursa bile, saatleri yine de farklı olabilir, bu da her gün jetonun çalışmayacağı bir Zaman Penceresine neden olabilir.
NickG

@NickG, bu sorunu daha önce yaşadım, bunu güvence altına almanın tek yolu sunucu saati isteyerek. Bu% 99 UTC sorununu ortadan kaldıracaktır. Elbette dezavantajı, sunucuya fazladan bir çağrıdır.
kororo

ama yine de bu belirteci kullanarak web hizmetinizi bir günlüğüne tüketebilirim değil mi? bunun nasıl yardımcı olacağını anlamıyorum
Mina Gabriel

@MinaGabriel, token oluşturmada daha fazla zaman çerçevesi ekleyebilirsiniz. (dakika * 10) + (saat * 100) + (gün * 1000) + (ay * 10000) + (yıl (son 2 hane) * 100000)
kororo

11

Uygulayabileceğiniz birkaç farklı yaklaşım var.

  1. RESTful sadık kişiler, TEMEL kimlik doğrulamasını kullanmanızı ve her istek üzerine kimlik bilgilerini göndermenizi isteyeceklerdir. Mantıkları, hiç kimsenin herhangi bir durumu depolamamasıdır.

  2. İstemci hizmeti, bir oturum kimliğini tutan bir tanımlama bilgisi depolayabilir. Bunu şahsen duyduğum bazı sadık kişiler kadar saldırgan bulmuyorum - tekrar tekrar kimlik doğrulaması yapmak pahalı olabilir. Görünüşe göre bu fikirden pek hoşlanmıyorsun.

  3. Açıklamanıza göre, gerçekten OAuth2 ile ilgileniyorsunuz gibi görünüyor. Şimdiye kadarki deneyimim, gördüğüm kadarıyla, biraz kafa karıştırıcı ve biraz kanayan bir kenar. Orada uygulamalar var, ancak çok az ve çok uzak. Java'da, Spring3'ün güvenlik modüllerine entegre edildiğini anlıyorum . (Onların öğretici Orada bir uzantısı olacak olmadığını görmek için bekliyorum güzel. Yazılır) Restlet teklif ettiği oldu rağmen, şimdiye kadar, ama ve kuluçka olabilir, hala tam olarak dâhil sürülmemiştir.


Seçenek 2'ye karşı hiçbir şeyim yok - bir RESTful uygulamasında iyi bir çözüm olduğunu düşünüyorum - ancak müşteri hizmeti jetonu ilk etapta nereden alıyor? İlk seferinde nasıl kimlik doğrulama yaparlar? Belki bunu yanlış düşünüyorum, ancak müşteri hizmetinin bunun için kendi kullanıcı adı ve şifresine sahip olması gerektiği garip görünüyor.
Tommi

Son kullanıcı sizin bir kullanıcınızsa, aracı hizmet kimlik bilgilerini ilk talepte size iletebilir ve siz de bir çerez veya başka bir belirteç iade edebilirsiniz.
jwismar

Benzer şekilde, OAuth senaryosunda, son kullanıcı web hizmetinize erişim yetkisini aracı hizmete devreder.
jwismar

Bir yanlış anlaşılma var gibi görünüyor - müşteri hizmetinin arkasında hiçbir son kullanıcı yok . Durumu daha iyi açıklamak için sorumu güncelledim.
Tommi

1
Yukarıda listelenen 1 numaralı seçeneğin yalnızca HTTPS üzerinden yapılması gerektiğini eklemeliyim.
mr-sk

3

Yaklaşıma inanıyorum:

  1. İlk istek, müşteri id / şifre gönderir
  2. Benzersiz jeton için değişim kimliği / geçiş
  3. Jetonu, süresi dolana kadar sonraki her istekte doğrulayın

Nasıl uyguladığınızdan ve diğer belirli teknik ayrıntılardan bağımsız olarak oldukça standarttır.

Zarfı gerçekten zorlamak istiyorsanız, belki de istemcinin https anahtarını kimlik bilgileri doğrulanana kadar geçici olarak geçersiz bir durumda kabul edebilir, hiç değilse bilgileri sınırlayabilir ve geçerliliğin sona ermesine bağlı olarak doğrulandıklarında erişim izni verebilirsiniz.

Bu yardımcı olur umarım


3

İstemci sertifikası yaklaşımı devam ederken, istemci sertifikası olmayan kullanıcılara hala izin verirken uygulanması çok zor olmayacaktır.

Kendinden imzalı bir Sertifika Yetkilisi oluşturduysanız ve her müşteri hizmetine müşteri sertifikaları verdiyseniz, bu hizmetleri doğrulamanın kolay bir yoluna sahip olurdunuz.

Kullandığınız web sunucusuna bağlı olarak, bir istemci sertifikasını kabul edecek, ancak gerektirmeyen bir istemci kimlik doğrulamasını belirtmek için bir yöntem olmalıdır. Örneğin, Tomcat'te https bağlayıcınızı belirtirken, 'true' veya 'false' yerine 'clientAuth = want' ayarlayabilirsiniz. Daha sonra, kendinden imzalı CA sertifikanızı güven deponuza (web sunucusu yapılandırmanızda başka bir dosya belirtmediyseniz, varsayılan olarak kullandığınız JRE'deki cacerts dosyası) eklediğinizden emin olursunuz, böylece yalnızca güvenilen sertifikalar, kendi imzalı CA'nız.

Sunucu tarafında, korumak istediğiniz hizmetlere yalnızca istekten bir istemci sertifikası alabiliyorsanız (boş değil) erişime izin verirsiniz ve herhangi bir ekstra güvenlik tercih ederseniz tüm DN kontrollerini geçerseniz. İstemci sertifikası olmayan kullanıcılar, hizmetlerinize yine de erişebilirler, ancak istekte hiçbir sertifika bulunmaz.

Bence bu en 'güvenli' yoldur, ancak kesinlikle öğrenme eğrisi ve ek yükü vardır, bu nedenle ihtiyaçlarınız için en iyi çözüm olmayabilir.


3

5. Başka bir şey - orada başka çözümler olmalı?

Haklısın, var! Ve buna JWT (JSON Web Jetonları) denir.

JSON Web Token (JWT), bir JSON nesnesi olarak taraflar arasında güvenli bir şekilde bilgi aktarımı için kompakt ve bağımsız bir yol tanımlayan açık bir standarttır (RFC 7519). Bu bilgiler, dijital olarak imzalandığı için doğrulanabilir ve güvenilir olabilir. JWT'ler bir gizli (HMAC algoritması ile) veya RSA kullanılarak bir genel / özel anahtar çifti kullanılarak imzalanabilir.

JWT'lere bakmanızı şiddetle tavsiye ederim. Alternatif çözümlerle karşılaştırıldığında, soruna çok daha basit bir çözümdür.

https://jwt.io/introduction/


1

Sunucuda Oturum oluşturabilir sessionIdve her REST çağrısıyla istemci ve sunucu arasında paylaşabilirsiniz .

  1. İlk kimlik doğrulaması DİNLENME isteği: /authenticate. Yanıtı (müşteri formatınıza göre) sessionId: ABCDXXXXXXXXXXXXXX;

  2. Bu Mağaza sessionIdiçinde Mapfiili oturumu ile. Map.put(sessionid, session)veya SessionListenersizin için anahtarlar oluşturmak ve yok etmek için kullanın;

    public void sessionCreated(HttpSessionEvent arg0) {
      // add session to a static Map 
    }
    
    public void sessionDestroyed(HttpSessionEvent arg0) {
      // Remove session from static map
    }
    
  3. Her REST çağrısında oturum kimliği alın, örneğin URL?jsessionid=ABCDXXXXXXXXXXXXXX(veya başka bir şekilde);

  4. Kullanarak HttpSessionharitadan geri alın sessionId;
  5. Oturum aktifse, o oturum için talebi doğrulayın;
  6. Yanıt veya hata mesajını geri gönderin.

0

Kullanıcı isteği onayladıktan sonra, kimlik doğrulama için diğer uygulama tarafından kullanılan benzersiz bir belirteç oluşturarak, bir uygulamanın bir kullanıcıyı bir uygulama kimliği parametresiyle sitenize yönlendirmesini isterim. Bu şekilde diğer uygulamalar kullanıcı kimlik bilgilerini işlemez ve diğer uygulamalar kullanıcılar tarafından eklenebilir, kaldırılabilir ve yönetilebilir. Foursquare ve birkaç başka site bu şekilde kimlik doğrulaması yapıyor ve diğer uygulama olarak uygulanması çok kolay.


Hmm, açıklamayı takip edip edemediğimden emin değilim. Hangi kullanıcıdan bahsediyoruz? Başka bir uygulama ile iletişim kuran uygulama hakkında konuşuyorum. Sanırım bunu anladınız, ama hala tam olarak anlayamıyorum. Örneğin, bu "jetonun" süresi dolduğunda ne olur?
Tommi

Oluşturduğunuz ve diğer uygulamaya geri gönderdiğiniz simge kalıcı bir belirteçtir, kullanıcıya ve uygulamaya bağlıdır. İşte foursquares docs developer.foursquare.com/docs/oauth.html adresine bir bağlantı ve bu sadece temelde oauth2, bu yüzden iyi bir kimlik doğrulama çözümü için buna bakın.
Devin M

Bir yanlış anlaşılma var gibi görünüyor - müşteri hizmetinin arkasında hiçbir son kullanıcı yok . Bağlandığınız foursquare dokümantasyonunda kısaca kullanıcı gerektirmeyen erişimden bahsediliyor, bu yüzden en azından biraz yardımcı oldu - teşekkürler! Ama hala gerçekte nasıl çalışacağına dair tam bir resim oluşturamıyorum.
Tommi

Sadece uygulamalar için anahtarlar oluşturun, o zaman yaptığınız tek şey uygulamalara erişim izni vermekse, basit bir application_id ve application_key kimlik doğrulaması için çalışmalıdır. Bir belirteç ile kimlik doğrulamalarını sağlamak istiyorsanız, aygıtın belirteç kimlik doğrulama seçeneklerini kullanmaya bakın, çünkü bu yalnızca uygulamanıza url isteği ile iletilen bir parametre olacaktır.
Devin M

Ancak bu kullanıcı adı + şifre = oturum kimlik doğrulama belirteci senaryosuyla tam olarak aynı değil mi? Application_id ve application_key yalnızca kullanıcı adı ve parolanın eş anlamlıları değil mi? :) Bu gerçekten böyle bir durum için standart uygulama ise gayet iyi - dediğim gibi, bu konuda deneyimsizim - ama başka seçenekler olabileceğini düşündüm ...
Tommi

-3

Kimlik doğrulamanın yanı sıra, büyük resmi düşünmenizi öneririm. Herhangi bir kimlik doğrulaması olmadan arka uç RESTful hizmetinizi yapmayı düşünün; daha sonra son kullanıcı ile arka uç hizmeti arasına çok basit kimlik doğrulama gerektiren orta katman hizmeti koyun.


Son kullanıcı ile arka uç hizmeti arasında mı? Bu, müşteri hizmetlerini tamamen yetkisiz bırakmaz mı? İstediğim bu değil. Elbette bu orta katmanı web hizmetim ve istemci hizmetlerim arasına yerleştirebilirim, ancak bu yine de soruyu açık bırakıyor: gerçek kimlik doğrulama modeli ne olurdu?
Tommi

Orta katman Nginx gibi bir web sunucusu olabilir, orada kimlik doğrulama yapabilirsiniz. Kimlik doğrulama modeli oturuma dayalı olabilir.
Dagang

Sorumda açıklamaya çalıştığım gibi, bu istemci hizmetleri için oturum tabanlı bir kimlik doğrulama şeması istemiyorum. (Lütfen soru ile ilgili güncellemelerime bakın.)
Tommi

İsim & şifre yerine beyaz ip listesi veya ip aralığı kullanmanızı öneririm. Genellikle, istemci hizmeti ip'si kararlıdır.
Dagang
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.