web-dev-qa-db-ja.com

Spring Securityトークン認証-RESTful JSONサービス

私は厳密にJSON WebサービスになるSpring MVCアプリケーションにSpring Securityを使用したいと考えています。私はいくつかの調査を行い、いくつかの記事を読みましたが、完全なものは実際には見つかりませんでした。アプリケーションを完全にステートレスにし、トークンベースの認証を使用する必要があります。 Spring MVCアプリケーションでフォームを使用したり、フォームを使用して認証したりしたくない。 JSONで要求とデータを厳密に受け取り、JSON応答を返す必要があります。

Angular JSクライアントアプリケーションは、ユーザー名とパスワードを送信し、アプリケーションからトークンを取得して順次リクエストで使用する必要があります。ある時点でAndroidこのWebサービスにもアクセスするクライアント。

Spring Securityは内部的にトークンをユーザーセッションにマッピングする方法を持っていると仮定しています。つまり、トークンXXXXXXXXXXXXは管理者ユーザーBobであり、トークンAAAAAAAAAAは​​標準ユーザーJoeであることを意味しています。しかし、私はSpring Securityの経験があまりないので、これがどのように組み合わされるのかわかりません。コントローラーおよびサービスメソッドでセキュリティで保護された注釈を使用できるようにしたいです。

Spring Securityでこれを達成する方法はありますか?

この質問は開始するのに適した場所のように思えますが、想像したとおりに機能するかどうかはわかりません RESTful Authentication via Spring

23
greyfox

これは Spring-Rest-Boilerplate で始めるのに適した場所です。

  1. 初めてhttp基本認証を使用してからログイン(ユーザー名/パスワードの送信)を行う必要があり、これによりトークンが返されます。
  2. 後続のリクエストでは、このトークンを認証に使用します。
  3. トークンに基づいてその認証を行うフィルターをチェーンに追加する必要があります。

トークン形式とそのための暗号化を考え出す必要があります。トークンの有効期限も保持することが理想的です。ユーザー名とともに有効期限もトークンの一部になる可能性があります。 暗号化アルゴリズム MD5のような暗号化ハッシュ関数。トークン全体のハッシュを取得します。

EditMaciejStępyraMD5が破損しているように、より強力なSHA-256のようなハッシュ関数。

Springセキュリティはデフォルトでログインページにリダイレクトしますが、これはREST=の場合は意味をなさないため、configでカスタムAuthenticationEntryPointを使用します(githubコードのサンプルを参照)。

トークンに次の形式を使用していました:token:username:hash:expiry

hash = MD5(ユーザー名+ magickey)

expiry = current_timestamp + mins_to_expiry

 <security:http realm="Protected API" use-expressions="true" auto-config="false" create-session="always" entry-point-ref="**CustomAuthenticationEntryPoint**">
        <security:custom-filter ref="**authenticationTokenProcessingFilter**" position="PRE_AUTH_FILTER" />
        <security:intercept-url pattern="/**" access="isAuthenticated()" />
 </security:http>

NB:コードに感謝dhavalnこれをリファレンスとして使用し、同様のものを開発しました。

18
M4ver1k

私の場合、org.springframework.security.web.context.SecurityContextRepository in org.springframework.security.web.context.SecurityContextPersistenceFilterいくつかのTomcatノード間でSecurityContextを共有する実装を使用します。クライアントはjsessionidのようなトークンを送信し続けますが、単純なラウンドロビンロードバランシングを行うことができ、セッションレプリケーションについて心配する必要はありません。

1
user2560528

「アプリケーションを完全にステートレスにしたい」

あなたがやろうとしていることを再考したい。ソリューションの良い例を見つけることができない理由があります:ステートレスで安全なアプリケーションを持つことができないのです。また、トークンをどこかに保存している場合は、ステートレスではありません。 JWTを使用してエンコードするなど、トークンを保存していない場合でも、ユーザーがWebブラウザーでトークンにアクセスする場合は、CSRF攻撃から保護する必要があります。あなたがあなたのルートに行くなら、たくさんのカスタマイズされたセキュリティコードを書くことを期待してください(これは悪いことです)。こちらの議論をご覧ください: https://spring.io/blog/2015/01/12/the-login-page-angular-js-and-spring-security-part-ii

1
user64141