ログインメカニズムとしてBASIC認証でjetty 6.1.22を使用しています。Web アプリに初めてログインすると、ブラウザーはユーザー名とパスワードを要求します。
session.invalidate() を使用してログアウトしようとすると、セッションは無効になりますが、資格情報はキャッシュされます。つまり、セキュリティで保護された URL に接続しようとすると、別のセッション ID が表示されますが、ユーザー名とパスワードのダイアログは表示されません。
ログインメカニズムとしてBASIC認証でjetty 6.1.22を使用しています。Web アプリに初めてログインすると、ブラウザーはユーザー名とパスワードを要求します。
session.invalidate() を使用してログアウトしようとすると、セッションは無効になりますが、資格情報はキャッシュされます。つまり、セキュリティで保護された URL に接続しようとすると、別のセッション ID が表示されますが、ユーザー名とパスワードのダイアログは表示されません。
(この質問は古いと思いますが、他の人が答えを求めているかもしれません)
BASIC認証はあなたが求めているものを実際には許可しませんが、いくつかの「癖」を受け入れる気があるなら、あなたが望むものに少し似たものを得ることができます.
BASIC 認証には、この方法での制御を困難にする 2 つの側面があります。
これらの側面はどちらも機能ですが、BASIC 認証を Java セッションにリンクすることは困難です。そのため、別のログイン メカニズム (Java FORM ログインなど) が存在します。
BASIC 認証はステートレス
です。これは、クライアントがサーバー側で何が起こっているのかまったくわからないことを意味し、BASIC 認証資格情報のセットを Cookie にリンクする方法がまったくないことを意味します (これは主に Java セッションを制御するものです)。ブラウザーが停止することを決定するまで (通常は、ブラウザーが閉じられ、新しいブラウザー セッションが作成されたため)、ブラウザーはすべての
要求で
ユーザー名とパスワードを送信するだけです。
ブラウザーは、サーバーが資格情報を使用して何をしているかを知りません。それらがもう必要かどうかはわかりません。また、サーバー側が「新しいセッション」が開始されたと判断した時期もわかりません。リクエストごとにそのユーザー名とパスワードを送信し続けるだけです。
BASIC 認証はクライアント側
ユーザー/パスワードのダイアログはクライアントによって処理されます。サーバーが言うのは、「要求した URL にはユーザー名とパスワードが必要です。このセキュリティ レルムには 'xyz' という名前を付けました」.
サーバーは、ユーザーが毎回パスワードを入力しているかどうか、またはクライアントがパスワードをキャッシュしているかどうかを認識していません。そこに本当にユーザーがいるかどうか、またはパスワードがファイルから引き出されたかどうかはわかりません。
サーバーができる唯一のことは、「この URL にアクセスする前に、ユーザーとパスワードを提供する必要があります」と言うだけです。
偽装する方法
基本的に、ブラウザーが古い資格情報を送信しているときにそれを検出 (つまり、知識に基づいた推測) し、"Please give me a user+password" 応答 (HTTP 401) を再度送信する必要があります。
これを行う最も簡単な方法は、ユーザーがそのセッションに初めてログインしたことを検出し、401応答コードを送信するフィルターをアプリケーションに設定することです。何かのようなもの:
if(session.getAttribute("auth") == null)
{
response.setStatus(401);
response.setHeader("WWW-Authenticate", "basic realm=\"Auth (" + session.getCreationTime() + ")\"" );
session.setAttribute("auth", Boolean.TRUE);
writer.println("Login Required");
return;
}
その例では、セッションの作成時間でレルムに名前を付けました (あまりきれいではありませんが、別の形式にした方がよいでしょう)。これは、セッションを無効にするたびにセキュリティ レルムの名前が変更されることを意味し、クライアントが混乱するのを防ぐのに役立ちます (1 つだけ与えたのに、なぜ同じレルムに対してユーザーとパスワードを再度要求するのでしょうか?) .
クライアントの応答にはレルム名が含まれないため、新しいレルム名はサーブレット コンテナを混乱させることはありません。
ただし、ユーザーが最初にログオンしたときにパスワードを 2 回要求されないようにするのが秘訣です。そして、箱から出してすぐに、このソリューションはそれを行います-コンテナがそれを要求するために1回、次にフィルターが要求するときにもう一度。
2 つのログイン ボックスを取得しないようにする方法 4 つのオプションがあります。
コードで行う
独自のサーブレット/フィルター内ですべてのセキュリティを実行できて、サーブレット コンテナー (Jetty) からの助けが得られない場合は、それほど難しくありません。web.xml で BASIC 認証を無効にするだけで、すべてコードで実行できます。(かなりの作業があり、セキュリティ ホールを開いたままにしないようにする必要がありますが、概念的には非常に簡単です)
ほとんどの人はそれをしたくありません。
セカンダリ Cookie
ユーザーがアプリケーションにログインした後、ブラウザ セッションの終了時に有効期限が切れる Cookie (「認証済み」) を設定できます。この Cookie は、Java セッションではなくブラウザ セッションに関連付けられています。
Java セッションを無効にする場合、 「認証済み」 Cookieを無効にしないでください。
ユーザーが新しいJava セッション (つまり) にログインしても、まだ「認証済み」である場合は、既存のブラウザー セッションを再利用しており、おそらく既存の HTTP 認証資格情報を再利用していることがわかります。その場合、新しい資格情報を強制的に与えるというトリックを行います。session.getAttribute("auth")==null401
保護されていないルート URL
ルート URL が保護されておらず、これがユーザーが常にログインする URL であることがわかっている場合は、その URL に「auth」/チェックを入れるだけ401で問題が解決します。ただし、誤ってセキュリティ ホールを開けないように注意してください。
この URL には、ユーザーを「実際の」アプリ (保護されている) にリダイレクトする以外の機能はありません。
保護された 1 つの URL 保護され
た 1 つの URL があります (例: "/login")。
「auth」/401フィルターと同様に、すべてのページ (ログイン以外) に別のフィルター (または同じフィルター内の追加コード) を設定して、request.getUserPrincipal()が設定されているかどうかを確認します。そうでない場合は、ユーザーを「/login」にリダイレクトします。
はるかに簡単な解決策BASIC 認証の
代わりに FORM ログイン方法を使用するだけです。この問題を解決するために設計されています。