Kaynakları yeniden tasarlama / oturum açma veya / kaydetme?


122

Bir web uygulaması tasarlıyordum ve sonra api'min bir RESTful web hizmeti olarak nasıl tasarlanması gerektiğini düşünmeye başladım. Şimdilik, URI'lerimin çoğu geneldir ve çeşitli web uygulamaları için geçerli olabilir:

GET  /logout   // destroys session and redirects to /
GET  /login    // gets the webpage that has the login form
POST /login    // authenticates credentials against database and either redirects home with a new session or redirects back to /login
GET  /register // gets the webpage that has the registration form
POST /register // records the entered information into database as a new /user/xxx
GET  /user/xxx // gets and renders current user data in a profile view
POST /user/xxx // updates new information about user

SO ve google'da dolaştıktan sonra burada çok yanlış yaptığımı hissediyorum.

İle başlayarak /logoutGerçekten bilmiyorum, belki bu yana, GETbir şey - bu daha uygun olabilir POSTisteği /logout, daha sonra oturumu imha ve GETyönlendirme. Ve /logoutterim kalmalı mı?

Peki ya /loginve /register. Ben değişebilir /registeriçin /registrationama bu benim hizmet temel işleyiş şeklini değiştirmez - bu daha derin sorunları vardır eğer.

Bir /userkaynağı asla ifşa etmediğimi şimdi fark ediyorum . Belki bu bir şekilde kullanılabilir. Örneğin, kullanıcıyı alın myUser:

foo.com/user/myUser

veya

foo.com/user

Son kullanıcı, URI'de bu ekstra ayrıntıya ihtiyaç duymaz. Ancak görsel olarak hangisi daha çekici?

SO'da bu REST işi hakkında başka soruları da fark ettim, ancak mümkünse burada ortaya koyduğum şey hakkında biraz rehberlik yapmaktan gerçekten memnun olurum.

Teşekkürler!

GÜNCELLEME:

Ayrıca şu konularda da fikir almak istiyorum:

/user/1

vs

/user/myUserName

Yanıtlar:


63

Özellikle REST-ful olmadığı gibi bir şey öne çıkıyor: oturumu kapatmak için bir GET isteğinin kullanılması.

( http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Safe_methods adresinden )

Bazı yöntemler (örneğin, HEAD, GET, OPTIONS ve TRACE) güvenli olarak tanımlanır, yani bunlar yalnızca bilgi alma amaçlıdır ve sunucunun durumunu değiştirmemelidir. Başka bir deyişle, günlük tutma, önbelleğe alma, afiş reklamlarının sunulması veya bir web sayacını artırma gibi nispeten zararsız etkilerin ötesinde yan etkileri olmamalıdır. [...]

Sunucu tarafından [... H] andling [GET isteklerinin] teknik olarak hiçbir şekilde sınırlı değildir. Bu nedenle, dikkatsiz veya kasıtlı programlama, sunucuda önemsiz olmayan değişikliklere neden olabilir. Bu tavsiye edilmez, çünkü Web önbelleğe alma, arama motorları ve diğer otomatik aracılar için sorunlara neden olabilir [...]

Oturumu kapatma ve yeniden yönlendirme ile ilgili olarak, oturum kapatma URI'nize bir gönderi, oturum kapatma sonrası sayfaya yönlendiren bir 303 yanıtı verebilir.

http://en.wikipedia.org/wiki/Post/Redirect/Get

http://en.wikipedia.org/wiki/HTTP_303

URL tasarımıyla ilgili endişeleri gidermek için düzenleyin:

"Kaynaklarımı nasıl tasarlarım?" benim için önemli bir soru; "URL'lerimi nasıl tasarlarım?" iki alanda bir husustur:

Kullanıcıların göreceği URL'ler mümkünse çok çirkin ve anlamlı olmamalıdır; Çerezlerin isteklerde bazı kaynaklara gönderilmesini, ancak diğerlerine gönderilmesini istemiyorsanız, yollarınızı ve çerez yollarınızı yapılandırmak istersiniz.

Eğer JRandomUseristekleri kendi profiline bakmak ve URL daha güzel olmasını istiyorum foo.com/user/JRandomUserya foo.com/user/(JRandom's numeric user id here), sadece kendi bilgilerine bakmak için bir kullanıcı için ayrı bir URL yapabilir:

GET foo.com/profile /*examines cookies to figure out who 
                     * is logged in (SomeUser) and then 
                     * displays the same response as a
                     * GET to foo.com/users/SomeUser.
                     */

Bu konudaki bilgelikten çok daha kolay bir şekilde cehaleti iddia ediyorum, ancak işte birkaç kaynak tasarımı düşüncesi:

  1. Tüketici: Hangi kaynakların doğrudan bir tarayıcıda görüntülenmesi, XHR aracılığıyla yüklenmesi veya başka türden bir istemci tarafından erişilmesi amaçlanıyor?
  2. Erişim / kimlik: yanıt tanımlama bilgilerine veya yönlendirenlere bağlı mı?

1
Harika cevap, teşekkürler! Ayrı URL önerinizi ( GET foo.com/profile/) uygulayacak olsaydım, bu, momo'nun önerdiği gibi sunum katmanının bir parçası olur muydu? Başka bir deyişle, bu GETistek tam olarak ne iade edilmelidir ? Bir web sayfası mı yoksa biraz JSON mu?
Qcom

2
Ah, şimdi anladığımı düşünüyorum. Momo'nun cevabı işleri gerçekten açıklığa kavuşturdu. RESTful API'sı için çok sayıda platformu sağlamak için inşa edilmiştir Yani GET, POST, PUT, ve DELETEkaynakların. Web sitesi, API'ye erişen başka bir platformdur. Diğer bir deyişle, web sitesi URL tasarımı, RESTful API tasarımından tamamen farklıdır. Lütfen hala yanılıyorsam söyle haha.
Qcom

Evet, REST API'nizi bir dizi URL ve web sitenizi farklı bir dizi yapın. Ardından, web sitenizin URL'si size uygun HTML + Javascript'i geri vermelidir, böylece sayfa, API URL'lerinize bir istemci olarak hareket etmek için uygun XmlHttpRequest'ler yapacaktır.
ellisbben

129

RESTful, URL'lerin oluşturulması için bir kılavuz olarak kullanılabilir ve oturumlar ve kullanıcı kaynakları oluşturabilirsiniz:

  • GET /session/new giriş formunun bulunduğu web sayfasını alır
  • POST /session kimlik bilgilerini veritabanına göre doğrular
  • DELETE /session oturumu yok eder ve / konumuna yönlendirir
  • GET /users/new kayıt formunun bulunduğu web sayfasını alır
  • POST /users girilen bilgileri yeni / kullanıcı / xxx olarak veritabanına kaydeder
  • GET /users/xxx // bir profil görünümünde mevcut kullanıcı verilerini alır ve işler
  • POST /users/xxx // kullanıcı hakkındaki yeni bilgileri günceller

Bunlar çoğul veya tekil olabilir (hangisinin doğru olduğundan emin değilim). Genellikle /usersbir kullanıcı dizin sayfası (beklendiği gibi) ve /sessionskimin oturum açtığını (beklendiği gibi) görmek için kullandım.

URL'de bir numara ( /users/43vs. /users/joe) yerine adın kullanılması , genellikle herhangi bir teknik gereksinimden değil, kullanıcılara veya arama motorlarına daha samimi olma arzusundan kaynaklanır. İkisi de iyi, ancak tutarlı olmanızı tavsiye ederim.

Kayıt / giriş / çıkış ile giderseniz veya sign(in|up|out)dinlendirici terminoloji ile aynı şekilde çalışmazsa düşünüyorum.


6
Müthiş! Bu kaynakları nasıl adlandırdığını beğendim; bu oldukça temiz. Duyduğum kadarıyla, ekleme değil, olsa /newiçin GET /session/sigara dinlendirici? Ben fiiller genellikle HTTP fiilleri (bırakılıyor duydum GET, POSTvs.).
Qcom

2
@Zach new bir fiil değildir. Bu durumda, bu bir oturumun alt kaynağıdır.
Kugel

DELETE / oturumda hangi oturumun silineceği nasıl belirlenir? Curl, DELETE isteğinde ne çerez ne de herhangi bir parametre göndermez. Sanırım - sadece DELETE / session / sessionId kullanmak için? Diğer bir soru, POST / oturumda oturum kimliğinin nasıl ve hangi formatta döndürüleceği.
Tvaroh

9
Huzurlu olmak gerçekten de kendinizi mutsuz etmenin ve hiç önemi olmayan şeylerle zaman kaybetmenin bir yoludur.
Jian Chen

6
Şahsen, formu (/ yeni) döndüren rotalara sahip olma fikrinden hoşlanmıyorum. Bu, görüş ve iş mantığı arasındaki ayrımı ortadan kaldırır. Dedi ki, / yeni rotalar olmadan önerilen yol mükemmel görünüyor.
Scadge

60

Oturumlar RESTful değil

  • Evet biliyorum. Genellikle OAuth ile yapılıyor, ancak gerçekten oturumlar RESTful değil. Öncelikle / login / logout kaynağınız olmamalıdır çünkü oturumlarınız olmamalıdır.

  • Eğer yapacaksanız, RESTful yapın. Kaynaklar isimdir ve / login ve / logout isim değildir. / Session ile giderdim. Bu, yaratmayı ve silmeyi daha doğal bir eylem haline getirir.

  • Oturumlar için POST ve GET karşılaştırması kolaydır. Değişken olarak kullanıcı / parola gönderiyorsanız, POST kullanırım çünkü parolanın URI'nin bir parçası olarak gönderilmesini istemiyorum. Günlüklerde görünecek ve muhtemelen tel üzerinde açığa çıkacaktır. Ayrıca GET argümanları sınırlamalarında yazılımın başarısız olma riskini de taşırsınız.

  • Genellikle Temel Kimlik Doğrulama kullanıyorum veya REST hizmetleri ile Kimlik Doğrulama kullanmıyorum.

Kullanıcı oluşturma

  • Bu tek bir kaynaktır, bu yüzden ihtiyacınız / kaydolmanız gerekmez.

    • POST / kullanıcı - İstekte bulunan kişi kimliği belirtemezse bir kullanıcı oluşturur
    • PUT / kullanıcı / xxx - Kimliği önceden bildiğinizi varsayarak bir kullanıcı oluşturun veya güncelleyin
    • GET / kullanıcı - x kullanıcı kimliğini listeler
    • GET / kullanıcı / xxx - xxx kimliğine sahip kullanıcının ayrıntılarını alır
    • DELETE / kullanıcı / xxx - xxx kimliğine sahip kullanıcıyı sil
  • Hangi tür kimliğin kullanılacağı zor bir sorudur. SİLDİ olan eski kimliklerin yeniden kullanımı hakkında benzersizliği zorunlu kılmayı düşünmelisiniz. Örneğin, kimlikler geri dönüştürülecekse (mümkünse) bu kimlikleri arka uçta yabancı anahtar olarak kullanmak istemezsiniz. Arka uç gereksinimlerini azaltmak için harici / dahili kimlik dönüşümü için bir arama yapabilirsiniz.


6
Bu en iyi cevap. / login ve / logout kaynak değildir ve REST fikrini bozar.
wle8300

5
Kimlik Doğrulama! = Oturum
dietbuddha

1
Evet, Fielding'in tezi bölüm 5.1.3'te "oturum durumunun [...] tamamen istemcide tutulduğunu" belirtir. Ayrıca, ideal olarak, kimlik doğrulamasının sunucu tarafında da durumsuz olması gerektiğini, yani bir veritabanında etkin "kimlik doğrulama biletlerini" depolamak yerine, sunucunun yalnızca kimlik bilgisinin kendisine dayalı olarak bir kimlik doğrulama kimlik bilgilerini doğrulayabilmesi gerektiğini, örneğin, özel bir anahtarla birlikte kendi kendine yeten bir şifreleme belirteci kullanarak. Yani, bir / session kaynağı yerine bir / authentication kaynağı tanıtılabilir, ancak bu da sorunu gerçekten çözmez ...
raner

Aslında, / login ve / logout isimdir. / Log_in ve / log_out düşündüğünüzü varsayıyorum.
TiggerToo

21

Müşterilerim için çeşitli REST Web Hizmetlerini entegre etme deneyimimden bahsedeceğim, ister mobil uygulamalar için, ister sunucudan sunucuya iletişim için kullanılsın, hem de başkaları için REST API oluştursun. İşte başkalarının REST API'sinden ve kendi oluşturduğumuz gözlemlerden topladığım birkaç gözlem:

  • API dediğimizde, normalde programlama arayüzü kümesine atıfta bulunur ve sunum katmanına gerek yoktur. REST ayrıca veri merkezlidir ve sunum odaklı değildir. Bu, çoğu REST verisini JSON veya XML biçiminde döndürdüğünü ve nadiren belirli bir sunum katmanını döndürdüğünü söyledi. Bu özellik (doğrudan web sayfası değil, geri dönen veri) REST'e çok kanallı dağıtım yapma yeteneği verdi. Bu, aynı web hizmetinin HTML, iOS, Android'de işlenebileceği ve hatta sunucudan sunucuya kombinasyon olarak kullanılabileceği anlamına gelir.
  • Hem HTML hem de REST'i bir URL olarak birleştirmek çok nadirdir. Varsayılan olarak REST, hizmet olarak düşünülür ve sunum katmanına sahip değildir. Web servislerini tüketenlerin aradıkları servislerden gelen veriyi istediklerine göre sunmaları işidir. Bu noktaya kadar, aşağıdaki URL'niz şimdiye kadar karşılaştığım çoğu REST tabanlı tasarıma (ya da Facebook veya Twitter'dan gelenler gibi standartlara) uymuyor
GET / kayıt // kayıt formunun bulunduğu web sayfasını alır
  • Önceki noktadan devam edersek, REST tabanlı hizmetin aşağıda önerilenler gibi yeniden yönlendirme yapması da nadirdir (ve ben karşılaşmadım):
GET / logout // oturumu yok eder ve / konumuna yönlendirir
POST / login //, veri tabanına göre kimlik bilgilerini doğrular ve yeni bir oturumla evi yeniden yönlendirir veya / login konumuna yeniden yönlendirir
 

REST hizmet olarak tasarlandığından, oturum açma ve oturum kapatma gibi işlevler normalde başarı / başarısızlık sonucunu döndürür (normalde JSON veya XML veri biçiminde) ve bu sonuç daha sonra tüketicinin yorumlayacağı anlamına gelir. Bu tür yorumlar, belirttiğiniz gibi uygun web sayfasına yönlendirmeyi içerebilir

  • REST'te URL, gerçekleştirilen eylemleri belirtir. Bu nedenle, mümkün olduğunca belirsizliği ortadan kaldırmalıyız. Sizin durumunuzda, farklı eylemleri gerçekleştiren aynı yola (/ register gibi) sahip hem GET hem de POST'a sahip olmak meşru olsa da, bu tür bir tasarım, sağlanan hizmetlerde belirsizlik yaratır ve hizmetlerinizin tüketicisinin kafasını karıştırabilir. Örneğin, aşağıda sunduğunuz gibi URL'ler REST tabanlı hizmetler için ideal değildir.
GET / kayıt // kayıt formunun bulunduğu web sayfasını alır
POST / register // girilen bilgileri veritabanına yeni / kullanıcı / xxx olarak kaydeder

Bunlar, uğraştığım şeyden bazı noktalar. Umarım sizin için bazı bilgiler sağlayabilir.

Şimdi REST'inizin uygulanmasına gelince, bunlar karşılaştığım tipik uygulama:

  • GET / çıkış  
    

    Arka uçta oturumu kapatın ve işlemin başarılı / başarısız olduğunu belirtmek için JSON döndürür

  • POST / giriş
    

    Kimlik bilgilerini arka uca gönderin. Başarı / başarısızlık döndür. Başarılı olursa, normalde oturum belirtecinin yanı sıra profil bilgilerini de döndürür.

  • POST / kayıt
    

    Arka uca kaydı gönderin. Başarı / başarısızlık döndür. Başarılı olursa, normalde başarılı oturum açma olarak kabul edilir veya kaydı ayrı bir hizmet olarak yapmayı seçebilirsiniz

  • GET / kullanıcı / xxx
    

    Kullanıcı profilini alın ve kullanıcının profili için JSON veri biçimini döndürün

  • POST / kullanıcı / xxx 
    // olarak yeniden adlandırıldı 
    POST / updateUser / xxx
    

    Güncellenen profil bilgilerini JSON biçiminde yayınlayın ve arka uçtaki bilgileri güncelleyin. Başarıyı / başarısızlığı arayan kişiye döndür


3
Evet, REST API'nizi HTML tabanlı uygulamayla (Javascript ve AJAX aracılığıyla) entegre ediyorsanız, JSON Javascript tarafından yerel olarak ayrıştırıldığından çok büyük avantajlar elde edeceksiniz. Android / Java'da JSON, XML'e kıyasla daha kolay ve daha kolay ayrıştırılır.
momo

15
GET / oturumu kapatmak tehlikelidir. GET idempotent olmalıdır. Ayrıca tarayıcılar <a> href'leri önceden getirmeyi sever, bu da oturumunuzu kapatır!
Kugel

4

Bunun kimlik doğrulamaya RESTful bir yaklaşım olduğuna inanıyorum. LogIn için kullanırsınız HttpPut. Bu HTTP yöntemi, anahtar sağlandığında ve tekrarlanan çağrılar idempotent olduğunda oluşturma için kullanılabilir. LogOff için, HttpDeleteyöntem altında aynı yolu belirtirsiniz . Hiçbir fiil kullanılmadı. Doğru toplama çoğullama. HTTP yöntemleri amacı destekler.

[HttpPut]
[Route("sessions/current")]
public IActionResult LogIn(LogInModel model) { ... }

[HttpDelete]
[Route("sessions/current")]
public IActionResult LogOff() { ... }

İsterseniz akımı aktif olanın yerine koyabilirsiniz.


1

Twitter'a benzer bir kullanıcı hesabı URL'si kullanmanızı tavsiye ederim, burada kullanıcının hesap URL'si tıpkı foo.com/myUserNametwitter hesabıma https://twitter.com/joelbyler URL'si ile ulaşabileceğiniz gibi bir şey olurdu

POST gerektiren çıkış yapma konusunda katılmıyorum. API'nizin bir parçası olarak, bir oturumu devam ettirecekseniz, UUID biçimindeki bir oturum kimliği, bir kullanıcıyı takip etmek ve gerçekleştirilen eylemin yetkilendirildiğini onaylamak için kullanılabilecek bir şey olabilir. Daha sonra bir GET bile oturum kimliğini kaynağa iletebilir.

Kısacası, basit tutmanızı tavsiye ederim, URL'ler kısa ve akılda kalıcı olmalıdır.


Soru, API kaynakları ile ilgili. Cevabınız sunum katmanı ile ilgili.
Henno
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.