Programing

RESTful 웹 서비스-다른 서비스의 요청을 인증하는 방법?

crosscheck 2020. 7. 26. 12:24
반응형

RESTful 웹 서비스-다른 서비스의 요청을 인증하는 방법?


사용자뿐만 아니라 다른 웹 서비스 및 응용 프로그램에서도 액세스 해야하는 RESTful 웹 서비스를 설계하고 있습니다. 들어오는 모든 요청을 인증해야합니다. 모든 통신은 HTTPS를 통해 이루어집니다. 사용자 인증은 서비스에서 제공 하는 / session 자원에 사용자 이름 및 비밀번호를 (SSL 연결을 통해) POST하여 획득 한 인증 토큰을 기반으로 작동 합니다.

웹 서비스 클라이언트의 경우 클라이언트 서비스 뒤에 최종 사용자없습니다 . 요청은 예약 된 작업, 이벤트 또는 다른 컴퓨터 작업에 의해 시작됩니다. 연결 서비스 목록은 미리 알려져 있습니다 (분명히 추측합니다). 다른 (웹) 서비스에서 오는 이러한 요청을 어떻게 인증해야합니까? 해당 서비스에 대해 인증 프로세스를 가능한 한 쉽게 구현할 수 있지만 보안 비용은 들지 않기를 바랍니다. 이와 같은 시나리오의 표준 및 모범 사례는 무엇입니까?

내가 생각할 수있는 (또는 나에게 제안 된) 옵션 :

  1. 클라이언트 서비스가 "가짜"사용자 이름 및 비밀번호를 사용하도록하고 사용자와 동일한 방식으로 인증하십시오. 이 옵션이 마음에 들지 않습니다.

  2. 클라이언트 서비스에 대한 영구 애플리케이션 ID (어플리케이션 키도 가능)를 지정하십시오. 내가 아는 한 이것은 사용자 이름 + 비밀번호를 갖는 것과 같습니다. 이 ID와 키를 사용하여 각 요청을 인증하거나 추가 요청을 인증하기 위해 인증 토큰을 만들 수 있습니다. 어느 쪽이든, 나는이 옵션을 좋아하지 않습니다. 응용 프로그램 ID와 키를 가질 수있는 사람은 클라이언트를 가장 할 수 있기 때문입니다.

  3. 이전 옵션에 IP 주소 확인을 추가 할 수 있습니다. 이로 인해 가짜 요청을 수행하기가 더 어려워집니다.

  4. 클라이언트 인증서. 자체 인증 기관을 설정하고 루트 인증서를 작성하며 클라이언트 서비스에 대한 클라이언트 인증서를 작성하십시오. 그러나 몇 가지 문제가 있습니다 .a) 인증서 없이도 사용자가 인증 할 수 있도록 허용하는 방법과 b) 클라이언트 서비스 관점에서이 시나리오를 구현하는 것이 얼마나 복잡합니까?

  5. 다른 것-다른 해결책이 있어야합니까?

내 서비스는 Java에서 실행 중이지만 구현 원리에 관심이 많지 않고 기본 원칙에 더 관심이 있기 때문에 어떤 프레임 워크가 구축 될지에 대한 정보를 의도적으로 생략했습니다. 기본 프레임 워크에 관계없이 구현할 수 있습니다. 그러나 나는이 주제에 대해 약간의 경험이 없으므로 실제 구현에 대한 구체적인 팁과 예제 (유용한 타사 라이브러리, 기사 등)도 많이 높이 평가됩니다.


이 문제에 대한 해결책은 공유 비밀로 요약됩니다. 또한 하드 코딩 된 사용자 이름 및 암호 옵션을 좋아하지 않지만 매우 간단하다는 이점이 있습니다. 클라이언트 인증서도 좋지만 실제로는 많이 다른가요? 서버에는 인증서가 있고 클라이언트에는 인증서가 있습니다. 가장 큰 장점은 무차별 대입이 어렵다는 것입니다. 바라건대 당신은 그것을 막기 위해 다른 보호 장치를 가지고 있습니다.

클라이언트 인증서 솔루션에 대한 귀하의 A 지점은 해결하기 어렵다고 생각합니다. 당신은 지점을 사용합니다. if (client side certificat) { check it } else { http basic auth }나는 자바 전문가가 아니며 클라이언트 측 인증서를 만들기 위해 결코 협력하지 않았습니다. 그러나 빠른 구글은 우리를 당신의 골목을 바라 보는 이 튜토리얼로 안내 합니다.

이 "가장 좋은 것"에 대한 모든 논의에도 불구하고, "코드가 적을수록 덜 영리할수록 좋습니다"라는 또 다른 철학이 있음을 지적하겠습니다. (저는 개인적으로이 철학을 가지고 있습니다). 클라이언트 인증서 솔루션은 많은 코드처럼 들립니다.

OAuth에 대한 질문을 하셨지만 OAuth2 제안에는 SSL과 함께 사용해야하는 " 베어러 토큰 " 이라는 문제에 대한 솔루션이 포함되어 있습니다 . 간단하게하기 위해 하드 코딩 된 사용자 / 패스 (앱별로 하나씩 취소하여 개별적으로 취소 할 수 있음) 또는 매우 유사한 베어러 토큰을 선택한다고 생각합니다.


귀하의 질문을 읽은 후에는 요청을 수행하기 위해 특수 토큰을 생성합니다. 이 토큰은 특정 시간에 살게됩니다 (하루에 말하자).

다음은 인증 토큰을 생성하는 예제입니다.

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

예 : 2011 년 6 월 3 일

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

그런 다음 사용자 비밀번호로 연결하십시오 (예 : "my4wesomeP4ssword!").

11630my4wesomeP4ssword!

그런 다음 해당 문자열의 MD5를 수행하십시오.

05a9d022d621b64096160683f3afe804

요청을 할 때는 항상이 토큰을 사용하십시오.

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

이 토큰은 항상 고유하므로 이러한 종류의 보호는 항상 ur 서비스를 보호하기에 충분하다고 생각합니다.

희망은 도움이됩니다

:)


취할 수있는 여러 가지 접근 방식이 있습니다.

  1. RESTful 순수 주의자는 기본 인증을 사용하고 모든 요청에 ​​대해 자격 증명을 보내길 원합니다. 그들의 근거는 아무도 어떤 국가도 저장하지 않는다는 것입니다.

  2. 클라이언트 서비스는 쿠키를 저장하여 세션 ID를 유지합니다. 필자가 듣는 일부 순수 론자들만큼 개인적으로 불쾌감을 느끼지는 않습니다. 여러 번 인증하는 것이 비쌀 수 있습니다. 그래도이 아이디어를 좋아하지 않는 것 같습니다.

  3. 당신의 설명에서, 당신이 OAuth2에 관심이있는 것처럼 들린다. 지금까지 내가 본 것으로부터, 나의 경험은, 그것이 혼란스럽고, 일종의 번짐이다. 거기에는 구현이 있지만 그 사이에는 거의 없습니다. Java에서는 Spring3의 보안 모듈에 통합되어 있음을 이해 합니다. ( 자습서 가 훌륭하게 작성되었습니다.) Restlet에 확장이 있는지를 기다리고 있었지만 지금까지 제안되었지만 인큐베이터에있을 수는 있지만 아직 완전히 통합되지 않았습니다.


나는 그 접근법을 믿는다.

  1. 첫 번째 요청에서 클라이언트는 id / passcode를 보냅니다.
  2. 고유 토큰에 대한 교환 ID / 패스
  3. 만료 될 때까지 각 후속 요청에서 토큰 유효성 검사

is pretty standard, regardless of how you implement and other specific technical details.

If you really want to push the envelope, perhaps you could regard the client's https key in a temporarily invalid state until the credentials are validated, limit information if they never are, and grant access when they are validated, based again on expiration.

Hope this helps


As far as the client certificate approach goes, it would not be terribly difficult to implement while still allowing the users without client certificates in.

If you did in fact create your own self-signed Certification Authority, and issued client certs to each client service, you would have an easy way of authenticating those services.

Depending on the web server you are using, there should be a method to specify client authentication that will accept a client cert, but does not require one. For example, in Tomcat when specifying your https connector, you can set 'clientAuth=want', instead of 'true' or 'false'. You would then make sure to add your self signed CA certificate to your truststore (by default the cacerts file in the JRE you are using, unless you specified another file in your webserver configuration), so the only trusted certificates would be those issued off of your self signed CA.

On the server side, you would only allow access to the services you wish to protect if you are able to retrieve a client certificate from the request (not null), and passes any DN checks if you prefer any extra security. For the users without client certs, they would still be able to access your services, but will simply have no certificates present in the request.

In my opinion this is the most 'secure' way, but it certainly has its learning curve and overhead, so may not necessarily be the best solution for your needs.


5. Something else - there must be other solutions out there?

You're right, there is! And it is called JWT (JSON Web Tokens).

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA.

I highly recommend looking into JWTs. They're a much simpler solution to the problem when compared against alternative solutions.

https://jwt.io/introduction/


You can create Session on server and share sessionId in between client and server with each REST call.

  1. First authenticate REST request: /authenticate. Returns response (as per your client format) with sessionId: ABCDXXXXXXXXXXXXXX;

  2. Store this sessionId in Map with actual session. Map.put(sessionid, session) or use SessionListener to create and destroy keys for you;

    public void sessionCreated(HttpSessionEvent arg0) {
      // add session to a static Map 
    }
    
    public void sessionDestroyed(HttpSessionEvent arg0) {
      // Remove session from static map
    }
    
  3. Get sessionid with every REST call, like URL?jsessionid=ABCDXXXXXXXXXXXXXX (or other way);

  4. Retrive HttpSession from map using sessionId;
  5. Validate request for that session if session is active;
  6. Send back response or error message.

I would use have an application redirect a user to your site with an application id parameter, once the user approves the request generate a unique token that is used by the other app for authentication. This way the other applications are not handling user credentials and other applications can be added, removed and managed by users. Foursquare and a few other sites authenticate this way and its very easy to implement as the other application.


Besides authentication, I suggest you think about the big picture. Consider make your backend RESTful service without any authentication; then put some very simple authentication required middle layer service between the end user and the backend service.

참고URL : https://stackoverflow.com/questions/6134082/restful-web-service-how-to-authenticate-requests-from-other-services

반응형