2

RESTeasyフレームワークを使用してWebサービスを開発しています。BASIC認証を設定できましたが、正常に機能しています。もちろん、これに加えてSSLを使用する予定です。

プロセスは単純です(これが何であるかわからない場合は、HTTP基本認証について何か読んでください):

  1. すべてのリクエストは、リクエストヘッダーを分析するメソッドによってインターセプトされます。
  2. このヘッダーはデコードされ、ユーザー名とパスワードが抽出されます。
  3. 次に、このメソッドはデータベースにクエリを実行して、ユーザー名とパスワードが一致するかどうかを確認します。
  4. リクエストの進行に一致する場合は一致し、一致しない場合は401コードが返されます。

このアプローチでは、REST(およびHTTP自体)のステートレスな性質により、すべての要求はデータベースへの要求を意味します。

私の質問は、認証されたすべてのリクエストでデータベースにクエリを実行しないことは可能ですか?

考えられるヒント:Cookieを使用するメカニズムはありますか?

この質問は技術的に不可知論者です。


補足として:

このREST認証に関する情報はほとんどないと思います。ただのOAuth、OAuth、OAuth ...サードパーティのアプリケーションを認証したくない場合、情報はいたるところに散らばっていて、OAuthを使用しているような具体的な例はありません。REST Webサービスでの認証に関して何か良いアドバイスがあれば、ぜひ聞いてみてください。

ありがとうございました。

4

5 に答える 5

1

すべてのリクエストがデータベースクエリを必要としないように、Cookieを使用して「Authチケット」(GoogleではOAuth以外の参照が見つかる可能性があります)を実装するさまざまな方法があります。ただし、これらには通常、暗号鍵が含まれます。

ベストプラクティスが暗号化キーをソースファイルに保存することであるとは確信していません(ただし、これはチュートリアルが通常それを実装する方法です)。データベースにクエリを実行しません。

Perceptionが述べているように、ステートレスシステム設計にCookie(状態)を追加することは一種の不正行為です。

于 2012-01-18T21:00:26.933 に答える
1

データベースの中間としてmemcachedのようなものを使用します。クレデンシャルがキャッシュされているかどうかを確認し、リクエストを続行する場合、キャッシュされていない場合は、データベースからクレデンシャルをプルして、クレデンシャルを確認します。クレデンシャルが一致する場合は、将来のリクエストのためにそれらをキャッシュし、現在のリクエストを続行します。

memchacedへのアクセスは、パスワードが保存されているため、データベースへのアクセスと同じくらい安全でなければならないことに注意してください。これが、非常に多くのサイトがOAuthを使用している理由の1つです。特に、必要に応じて新しいアクセストークンを取得する短命のアクセストークンと長命の更新トークンを配布するOAuth2を使用しています。

于 2012-01-18T21:00:41.473 に答える
1

Representational State Transfer Securityの世界へようこそ!ご存知のとおり、私はRoy Fieldingにメッセージを送信して、安全で真にRESTfulなサービスを作成する方法を尋ねました。彼はまだ私に戻ってこない。

2つのオプションは、実際には基本認証(SSLを使用するか、要点)またはOAuthです。私が現在関わっているすべてのソリューションには、OAuthを使用しています。テストは複雑になりますが、非常に安全であり、サービスから外部化可能なAPIを作成できます。

セッション情報を保存するためにCookieを使用しないことをお勧めします。これはRESTの精神に違反するだけでなく、アプリケーションをセッションハイジャックにさらすことにもなります。処理を高速化するためにできることの1つは、ユーザー情報を含む適切な第2レベルのキャッシュを維持することです。これにより、クエリがすべての着信要求に対して実際にDBにヒットすることはありません。これにより、速度が大幅に向上します。この戦術は、基本認証とOauthの両方で同等に機能します。

于 2012-01-18T21:01:23.533 に答える
1

AppEningeのUserServiceと(そしてGoogleアカウントと)統合すると、クエリを防ぐことができます。RESTletには、フレームワークに付属する非常にエレガントなオーセンティケーターがあります。

public class GaeAuthenticator extends Authenticator {
    /**
     * The GAE UserService that provides facilities to check whether a user has
     * authenticated using their Google Account
     */
    private UserService userService = UserServiceFactory.getUserService();

    /**
     * Constructor setting the mode to "required".
     * 
     * @param context
     *            The context.
     * @see #Authenticator(Context)
     */
    public GaeAuthenticator(Context context) {
        super(context);
    }

    /**
     * Constructor using the context's default enroler.
     * 
     * @param context
     *            The context.
     * @param optional
     *            The authentication mode.
     * @see #Authenticator(Context, boolean, Enroler)
     */
    public GaeAuthenticator(Context context, boolean optional) {
        super(context, optional);
    }

    /**
     * Constructor.
     * 
     * @param context
     *            The context.
     * @param optional
     *            The authentication mode.
     * @param enroler
     *            The enroler to invoke upon successful authentication.
     */
    public GaeAuthenticator(Context context, boolean optional, Enroler enroler) {
        super(context, optional, enroler);
    }

    /**
     * Integrates with Google App Engine UserService to redirect
     * non-authenticated users to the GAE login URL. Upon successful login,
     * creates a Restlet User object based values in GAE user object. The GAE
     * "nickname" property gets mapped to the Restlet "firstName" property.
     * 
     * @param request
     *            The request sent.
     * @param response
     *            The response to update.
     * @return True if the authentication succeeded.
     */
    @Override
    protected boolean authenticate(Request request, Response response) {
        ClientInfo info = request.getClientInfo();
        if (info.isAuthenticated()) {
            // The request is already authenticated.
            return true;
        } else if (userService.isUserLoggedIn()) {
            // The user is logged in, create restlet user.
            com.google.appengine.api.users.User gaeUser = userService
                    .getCurrentUser();
            User restletUser = new User(gaeUser.getUserId());
            restletUser.setEmail(gaeUser.getEmail());
            restletUser.setFirstName(gaeUser.getNickname());
            info.setUser(restletUser);
            info.setAuthenticated(true);
            return true;
        } else {
            // The GAE user service says user not logged in, let's redirect him
            // to the login page.
            String loginUrl = userService.createLoginURL(request
                    .getOriginalRef().toString());
            response.redirectTemporary(loginUrl);
            return false;
        }
    }
}
于 2012-01-21T10:31:51.367 に答える
0

答えは最終的にキャッシュになりました。

私の特定のケースでは、RESTフレームワークとしてRESTeasyを使用し、アプリケーションサーバーとしてGoogleAppEngineを使用していました。GAEがmemcacheをサポートしていることを見つけるのは難しくありませんでした。

Objectifyを使用している場合(本当にそうすべきです;それは素晴らしいです)、それはさらに簡単です。エンティティクラスに@Cachedアノテーションを付けるだけです。この手順をここに示します

Objectifyは、セッションオブジェクトで別の種類のキャッシュをサポートします。つまり、Objectifyオブジェクトがインスタンス化されている限り、memcacheを使用しなくてもオブジェクトを提供できます(GAEではmemcacheを使用するためのクォータがありますが、データストアのものよりも安価です)。ウィキでObjectifyのグッドプラクティスを読むことを強くお勧めします。

最後に、 Basicの代わりにダイジェスト認証を使用することを検討します。それははるかに安全なようです。パスワードがネットワークを通過しないという事実は、私を本当に安心させます。

このSOの質問が、誰かと私を助けてくれた人たちに役立つことを願っています。ありがとう。:)

于 2012-01-20T16:16:12.313 に答える