/ 로그인 또는 / 등록 리소스를 RESTfully 설계 하시겠습니까?


122

나는 웹 앱을 디자인하고 있었고 내 API가 RESTful 웹 서비스로 어떻게 디자인되어야하는지 생각하기 위해 멈추었습니다. 현재 대부분의 URI는 일반적이며 다양한 웹 앱에 적용될 수 있습니다.

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와 Google을 둘러 본 후 여기에서 많이 잘못하고 있다고 느낍니다.

로 시작 /logout하면 아마도 내가 GET아무것도 하지 않기 때문에 , 세션을 파괴 한 다음 리디렉션을 POST요청하는 것이 더 적절할 수 있습니다 . 그리고 그 기간이 유지 되어야 합니까?/logoutGET/logout

무엇에 대한 /login/register. 로 변경할 /register수는 /registration있지만 더 깊은 문제가있는 경우 내 서비스가 근본적으로 작동하는 방식을 변경하지는 않습니다.

이제는 /user리소스를 노출하지 않습니다 . 아마도 그것은 어떻게 든 활용할 수있을 것입니다. 예를 들어 다음과 같은 사용자를 가져옵니다 myUser.

foo.com/user/myUser

또는

foo.com/user

최종 사용자는 URI에 추가 상세 정보를 요구하지 않습니다. 그러나 어느 것이 시각적으로 더 매력적입니까?

이 REST 비즈니스에 대해 여기에서 다른 질문을 발견했지만 가능하면 여기에 배치 한 것에 대한 지침을 정말 감사하겠습니다.

감사!

최신 정보:

또한 다음에 대한 몇 가지 의견을 원합니다.

/user/1

vs

/user/myUserName

답변:


63

특히 REST-ful이 아닌 것으로 눈에 띄는 한 가지는 로그 아웃을 위해 GET 요청을 사용하는 것입니다.

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

일부 메서드 (예 : HEAD, GET, OPTIONS 및 TRACE)는 안전한 것으로 정의됩니다. 즉, 정보 검색 용으로 만 사용되며 서버 상태를 변경해서는 안됩니다. 즉, 로깅, 캐싱, 배너 광고 제공 또는 웹 카운터 증가와 같은 상대적으로 무해한 효과 이상의 부작용이 없어야합니다. [...]

[...] 서버에 의한 [GET 요청 처리] 처리는 기술적으로 어떤 식 으로든 제한되지 않습니다. 따라서 부주의하거나 의도적 인 프로그래밍으로 인해 서버에 사소하지 않은 변경이 발생할 수 있습니다. 이것은 웹 캐싱, 검색 엔진 및 기타 자동화 에이전트에 문제를 일으킬 수 있기 때문에 권장되지 않습니다. [...]

로그 아웃 및 리디렉션의 경우 로그 아웃 URI에 대한 게시물이 로그 아웃 후 페이지로 리디렉션되는 303 응답을 제공하도록 할 수 있습니다.

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

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

URL 디자인 문제를 해결하기 위해 편집 :

"자원을 어떻게 디자인합니까?" 나에게 중요한 질문입니다. "URL은 어떻게 디자인합니까?" 두 가지 영역에서 고려할 사항입니다.

사용자에게 표시되는 URL은 가능하면 너무 추하고 의미가 없어야합니다. 일부 리소스에 대한 요청에서 쿠키를 전송하고 다른 리소스에는 전송하지 않으려면 경로와 쿠키 경로를 구조화해야합니다.

경우 JRandomUser욕구가 자신의 프로필을보고하고 URL보다 예뻐 할 foo.com/user/JRandomUser또는 foo.com/user/(JRandom's numeric user id here), 당신은 단지 자신의 정보를보고 사용자에 대한 별도의 URL을 만들 수 있습니다 :

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.
                     */

나는이 주제에 대한 지혜보다 무지를 훨씬 더 쉽게 주장 할 것이지만, 여기에 몇 가지 리소스 설계 고려 사항이 있습니다.

  1. 소비자 : 브라우저에서 직접 보거나 XHR을 통해로드하거나 다른 종류의 클라이언트에서 액세스 할 수있는 리소스는 무엇입니까?
  2. 액세스 / 신원 : 응답이 쿠키 또는 리퍼러에 따라 달라 집니까?

1
감사합니다! 별도의 URL 제안 ( GET foo.com/profile/) 을 구현하려는 경우 momo가 제안한 것처럼 프레젠테이션 레이어의 일부가 될까요? 즉, 해당 GET요청이 정확히 무엇을 반환 해야 합니까? 웹 페이지 또는 일부 JSON?
Qcom 2011 년

2
아, 이제 본 것 같아요. Momo의 대답은 정말 일을 정리했습니다. 편안한 API는 여러 플랫폼을 할 수 있도록 구성되어 그래서 GET, POST, PUT, 및 DELETE자원을. 웹 사이트는 API에 액세스하는 또 다른 플랫폼입니다. 즉, 웹 사이트 URL 디자인은 RESTful API 디자인과 완전히 다릅니다. 내가 아직도 틀렸다면 말해줘 하하.
Qcom 2011 년

예, REST API를 하나의 URL 집합으로 만들고 웹 사이트를 다른 집합으로 만듭니다. 그런 다음 웹 사이트 URL이 적절한 HTML + Javascript를 제공하여 페이지가 API URL에 적절한 XmlHttpRequest를 만들어 클라이언트 역할을하도록합니다.
ellisbben 2011 년

129

RESTful은 URL 구성을위한 지침으로 사용할 수 있으며 세션사용자 리소스를 만들 있습니다.

  • GET /session/new 로그인 양식이있는 웹 페이지를 가져옵니다.
  • POST /session 데이터베이스에 대해 자격 증명을 인증합니다.
  • DELETE /session 세션을 파괴하고 /로 리디렉션
  • GET /users/new 등록 양식이있는 웹 페이지를 가져옵니다.
  • POST /users 입력 된 정보를 새로운 / user / xxx로 데이터베이스에 기록합니다.
  • GET /users/xxx // 프로필보기에서 현재 사용자 데이터를 가져오고 렌더링합니다.
  • POST /users/xxx // 사용자에 대한 새로운 정보를 업데이트합니다.

복수형 또는 단수형이 될 수 있습니다 (어떤 것이 올바른지 잘 모르겠습니다). 저는 보통 /users사용자 색인 페이지 (예상대로)를 사용하고 /sessions누가 로그인 했는지 (예상대로) 확인했습니다.

대신에 숫자 (의 URL에있는 이름을 사용하여 /users/43비교하는 /users/joe) 일반적으로 사용자에게 더 친절 또는 엔진이 아닌 기술적 요구 사항을 검색 할 욕망에 의해 구동된다. 어느 쪽이든 괜찮지 만 일관성을 유지하는 것이 좋습니다.

등록 / 로그인 / 로그 아웃 또는을 sign(in|up|out)사용하면 편안한 용어로는 잘 작동하지 않는 것 같습니다.


6
대박! 나는 당신이 그 자원을 어떻게 명사했는지를 좋아합니다. 꽤 깨끗합니다. 내가 무슨 소리를 들었어요에서 추가되지 않으며, 비록 /newGET /session/비 편안하고? 나는 동사는 일반적으로 HTTP 동사 (왼쪽 것을 들었다 GET, POST등).
Qcom 2011 년

2
@Zach new는 동사가 아닙니다. 이 경우 세션의 하위 리소스입니다.
Kugel 2013-04-19

DELETE / session에서 삭제할 세션을 결정하는 방법은 무엇입니까? Curl은 DELETE 요청에서 쿠키 나 매개 변수를 보내지 않습니다. 나는 가정한다-DELETE / session / sessionId를 사용하기 위해서? 또 다른 질문은 POST / session에서 세션 ID를 반환하는 방법과 형식입니다.
Tvaroh 2013

9
진정으로 안정은 자신을 불행하게 만들고 전혀 중요하지 않은 일에 시간을 낭비하는 방법입니다.
Jian Chen

6
개인적으로 양식 (/ new)을 반환하는 경로가 있다는 생각이 싫습니다. 이것은 뷰와 비즈니스 로직 사이의 분리를 깨뜨립니다. Tha는 / new 경로가 없으면 제안 된 경로가 완벽 해 보입니다.
Scadge

60

세션은 RESTful이 아닙니다

  • 네, 알아요. 일반적으로 OAuth로 완료되지만 실제로 세션은 RESTful이 아닙니다. 주로 세션이 없어야하므로 / login / logout 리소스가 없어야합니다.

  • 당신이 그것을 할 것이라면 RESTful로 만드십시오. 자원은 명사이고 / login 및 / logout은 명사가 아닙니다. 나는 / session으로 갈 것입니다. 이렇게하면 생성 및 삭제가보다 자연스러운 작업이됩니다.

  • 세션에 대한 POST 대 GET은 쉽습니다. 사용자 / 암호를 변수로 보내는 경우 암호가 URI의 일부로 전송되는 것을 원하지 않기 때문에 POST를 사용합니다. 로그에 표시되며 전선을 통해 노출 될 수 있습니다. 또한 GET 인수 제한으로 인해 소프트웨어가 실패 할 위험이 있습니다.

  • 일반적으로 기본 인증을 사용하거나 REST 서비스에 인증을 사용하지 않습니다.

사용자 생성

  • 하나의 리소스이므로 / register가 필요하지 않습니다.

    • POST / user-요청자가 ID를 지정할 수없는 경우 사용자를 만듭니다.
    • PUT / user / xxx-ID를 미리 알고 있다고 가정하고 사용자 생성 또는 업데이트
    • GET / user-x 사용자 ID 나열
    • GET / user / xxx-ID가 xxx 인 사용자의 세부 사항을 가져옵니다.
    • DELETE / user / xxx-ID가 xxx 인 사용자 삭제
  • 어떤 종류의 ID를 사용할지는 어려운 질문입니다. 고유성 적용, 삭제 된 이전 ID의 재사용에 대해 생각해야합니다. 예를 들어, ID가 재활용 될 경우 (가능한 경우) 백엔드에서 해당 ID를 외래 키로 사용하고 싶지 않습니다. 백엔드 요구 사항을 완화하기 위해 외부 / 내부 ID 변환을 조회 할 수 있습니다.


6
이것이 최고의 답변입니다. / login 및 / logout은 리소스가 아니며 REST 개념을 깨뜨립니다.
wle8300

5
인증! = 세션
dietbuddha

1
예, Fielding의 논문은 섹션 5.1.3에서 "[s] ession state는 [...] 전적으로 클라이언트에 유지됩니다."라고 설명합니다. 또한, 이상적으로는 인증이 서버 측에서도 상태 비 저장이어야한다고 주장합니다. 즉, 활성 "인증 티켓"을 데이터베이스에 저장하는 대신 서버가 자격 증명 자체를 기반으로 인증 자격 증명을 확인할 수 있어야합니다. 예를 들어 개인 키와 함께 자체 포함 된 암호화 토큰을 사용합니다. 따라서 / session 리소스 대신에 / authentication 리소스를 도입 할 수 있지만 실제로 문제를 해결하지는 못합니다 ...
raner

실제로 / login 및 / logout은 명사입니다. 나는 당신이 / log_in과 / log_out을 생각하고 있다고 가정합니다.
TiggerToo

21

모바일 앱에 사용 되든 서버 간 통신에 사용 되든 다른 사용자를 위해 REST API를 구축하든 클라이언트를 위해 다양한 REST 웹 서비스를 통합 한 경험을 간단히 말씀 드리겠습니다. 다음은 다른 사람의 REST API에서 수집 한 몇 가지 관찰과 우리가 직접 구축 한 관찰입니다.

  • API라고 할 때 일반적으로 프로그래밍 인터페이스 집합을 나타내며 프레젠테이션 계층이 필요하지 않습니다. REST는 또한 데이터 중심이며 프레젠테이션 기반이 아닙니다. 즉, 대부분의 REST는 JSON 또는 XML 형식으로 데이터를 반환하고 특정 프레젠테이션 레이어를 거의 반환하지 않습니다. 이 특성 (직접 웹 페이지가 아닌 데이터 반환)은 REST 기능을 통해 다중 채널 전달을 수행 할 수 있습니다. 동일한 웹 서비스를 HTML, iOS, Android로 렌더링하거나 서버 대 서버 조합으로 사용할 수도 있습니다.
  • HTML과 REST를 URL로 결합하는 것은 매우 드뭅니다. 기본적으로 REST는 서비스로서의 생각이며 프레젠테이션 계층이 없습니다. 웹 서비스를 사용하는 사람들이 원하는대로 호출하는 서비스에서 데이터를 렌더링하는 것이 작업입니다. 그 시점에서 아래 URL은 지금까지 만난 대부분의 REST 기반 디자인 (Facebook 또는 Twitter에서 온 사람들과 같은 표준도 아님)과 일치하지 않습니다.
GET / register // 등록 양식이있는 웹 페이지를 가져옵니다.
  • 이전 시점에서 계속해서 REST 기반 서비스가 아래에 제안 된 것과 같은 리디렉션을 수행하는 것은 드문 일입니다 (본 적이없는 경우도 있음).
GET / logout // 세션을 파괴하고 /로 리디렉션합니다.
POST / login // 데이터베이스에 대한 자격 증명을 인증하고 새 세션으로 홈을 리디렉션하거나 / login으로 다시 리디렉션합니다.
 

REST는 서비스로 설계되었으므로 로그인 및 로그 아웃과 같은 기능은 일반적으로 소비자가 해석 할 성공 / 실패 결과 (일반적으로 JSON 또는 XML 데이터 형식)를 반환합니다. 이러한 해석에는 귀하가 언급 한대로 적절한 웹 페이지로의 리디렉션이 포함될 수 있습니다.

  • REST에서 URL은 취해진 조치를 나타냅니다. 따라서 가능한 한 많은 모호성을 제거해야합니다. 귀하의 경우에는 서로 다른 작업을 수행하는 동일한 경로 (예 : / register)를 가진 GET 및 POST를 모두 갖는 것이 합법적이지만 이러한 디자인은 제공되는 서비스에 모호성을 유발하고 서비스 소비자를 혼동 할 수 있습니다. 예를 들어 아래에서 소개하는 것과 같은 URL은 REST 기반 서비스에 적합하지 않습니다.
GET / register // 등록 양식이있는 웹 페이지를 가져옵니다.
POST / register // 입력 된 정보를 새로운 / user / xxx로 데이터베이스에 기록

그것들은 제가 다루었던 몇 가지 요점입니다. 나는 그것이 당신에게 약간의 통찰력을 줄 수 있기를 바랍니다.

이제 REST 구현을 위해 다음과 같은 일반적인 구현이 발생했습니다.

  • GET / 로그 아웃  
    

    백엔드에서 로그 아웃을 실행하고 작업의 성공 / 실패를 나타내는 JSON을 반환합니다.

  • POST / 로그인
    

    백엔드에 자격 증명을 제출합니다. 성공 / 실패를 반환합니다. 성공하면 일반적으로 세션 토큰과 프로필 정보도 반환합니다.

  • POST / 등록
    

    백엔드에 등록을 제출하십시오. 성공 / 실패를 반환합니다. 성공하면 일반적으로 성공한 로그인과 동일하게 처리되거나 별도의 서비스로 등록하도록 선택할 수 있습니다.

  • / user / xxx 가져 오기
    

    사용자 프로필 가져 오기 및 사용자 프로필에 대한 JSON 데이터 형식 반환

  • POST / user / xxx 
    // 이름이 
    POST / updateUser / xxx
    

    업데이트 된 프로필 정보를 JSON 형식으로 게시하고 백엔드에서 정보를 업데이트합니다. 성공 / 실패를 호출자에게 반환


3
예, REST API를 HTML 기반 앱 (Javascript 및 AJAX를 통해)과 통합하는 경우 JSON이 Javascript에서 기본적으로 구문 분석되므로 엄청난 이점이 있습니다. Android / Java에서 JSON은 XML에 비해 파싱하기가 더 쉽고 간단합니다.
momo aug

15
GET / 로그 아웃은 위험합니다. GET은 멱등이어야합니다. 또한 브라우저는 <a> href를 미리 가져 와서 로그 아웃합니다!
Kugel 2013-04-19

4

나는 이것이 인증에 대한 RESTful 접근 방식이라고 생각합니다. 로그인의 경우 HttpPut. 이 HTTP 메서드는 키가 제공 될 때 생성에 사용할 수 있으며 반복되는 호출은 멱 등성입니다. LogOff의 경우 HttpDelete메서드 에서 동일한 경로를 지정합니다 . 사용 된 동사가 없습니다. 적절한 컬렉션 복수화. HTTP 메소드는 목적을 지원합니다.

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

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

원하는 경우 전류를 활성으로 대체 할 수 있습니다.


1

https://twitter.com/joelbylerfoo.com/myUserName URL을 사용하여 내 트위터 계정에 액세스 할 수 있는 것과 같은 사용자 계정 URL 인 twitter와 유사한 사용자 계정 URL을 사용하는 것이 좋습니다.

POST가 필요한 로그 아웃에 동의하지 않습니다. API의 일부로 세션을 유지하려는 경우 UUID 형식의 세션 ID는 사용자를 추적하고 수행중인 작업이 승인되었는지 확인하는 데 사용할 수있는 항목 일 수 있습니다. 그런 다음 GET조차도 세션 ID를 리소스에 전달할 수 있습니다.

간단히 말해서 URL은 기억에 남을만한 짧아야합니다.


문제는 API 리소스에 관한 것입니다. 귀하의 대답은 프레젠테이션 레이어에 관한 것입니다.
Henno
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.