1. http ステートレスプロトコル
Webアプリケーションはブラウザ/サーバーアーキテクチャを採用しており、通信プロトコルとしてhttpが使用されます。 http はステートレス プロトコルであり、ブラウザからの各リクエストはサーバーによって独立して処理され、次の図に示されているように、3 つのリクエスト/レスポンス ペア間には接続がありません。
しかし、これは、すべてのユーザーがブラウザを介してサーバー リソースにアクセスできることも意味します。サーバーの特定のリソースを保護したい場合は、ブラウザのリクエストを制限し、ブラウザのリクエストを識別し、正当なリクエストに応答する必要があります。ブラウザリクエストを識別するには、ブラウザリクエストのステータスを知る必要があります。 http プロトコルはステートレスであるため、サーバーとブラウザーが共同して状態を維持できるようにします。これがセッション メカニズムです
2. セッション メカニズム
ブラウザーがサーバーに初めてリクエストするとき、サーバーはセッションを作成し、応答の一部としてセッション ID をブラウザーに送信し、それを保存します。 2 回目は、セッション ID が最初と 3 番目のリクエストに含まれており、サーバーはリクエスト内のセッション ID を取得することで、それが同じユーザーであるかどうかを判断します。このプロセスは次の図に示されています。最初のリクエスト
サーバーはセッション オブジェクトをメモリに保存します。ブラウザはセッション ID をどのように保存しますか? 2つの方法が考えられます
- リクエストパラメータ
- cookie
各リクエストのパラメータとしてセッションIDを使用する サーバーはリクエストを受信すると、自然にパラメータを解析してセッションIDを取得できます。 、これを使用して、同じリクエストからのものであるかどうかを判断します。明らかに、このメソッドは信頼できません。次に、HTTP リクエストが送信されるたびにブラウザがセッション ID を自動的に送信できるようにします。これには Cookie メカニズムが使用されます。 Cookie は、ブラウザーが少量のデータを保存するために使用するメカニズムです。データは、ブラウザーが http リクエストを送信するときに、自動的に Cookie 情報を添付します
。Tomcat セッション メカニズムも実装されています。 Tomcat サーバーにアクセスすると、サーバー内に「JSESSIONID」という名前の Cookie が表示されます。これは、Tomcat セッション機構によって保持されるセッション ID です。ログイン ステータス
セッション メカニズムを使用すると、ログイン ステータスを簡単に理解できます。ブラウザが初めてサーバーにリクエストするときに、サーバーがユーザー名とパスワードを取得する必要があると想定されます。パスワードを確認し、データベース内でそれらを比較します。それが正しい場合は、現在このセッションを保持しているユーザーが正当なユーザーであることを意味します。これは、このセッションを「承認済み」または「ログイン済み」としてマークする必要があります。 Tomcat はセッション オブジェクトにログイン ステータスを次のように設定する必要があります
2
HttpSession session = request.getSession();
session.setAttribute("isLogin",true);
ユーザーが再度アクセスすると、Tomcat はセッション オブジェクトのログイン ステータスを確認します
|
12 |
HttpSesセッションセッション = request.getSession();
session.getAttribute("isLogin");
ログインステータスを実装するブラウザリクエストサーバーモデルは以下の図で説明されています
保護されたリソースがリクエストされるたびにセッションオブジェクトのログインステータスがチェックされ、isLogin=trueのセッションのみにアクセスできます。したがって、ログインメカニズムが実装されています。
2. 複数のシステムの複雑さ
Web システムは、古代の単一システムから、現在では複数のシステムで構成されるアプリケーション群へと長い発展を遂げてきましたが、ユーザーは 1 つずつログインしなければなりません。その後、1つずつログアウトしますか?下の図で説明されているように
Web システムは単一のシステムから複数のシステムで構成されるアプリケーション群に発展しました。その複雑さはユーザーではなくシステム自体が負担する必要があります。 Web システムが内部的にどれほど複雑であっても、ユーザーにとっては統一された全体です。つまり、ユーザーが Web システムのアプリケーション グループ全体にアクセスすることは、単一のシステムにアクセスするだけで十分です 。
単一システムのログイン ソリューションは完璧ですが、複数システムのアプリケーション グループには適しなくなったのはなぜでしょうか。
単一システムのログイン ソリューションの中核は Cookie であり、Cookie はブラウザとサーバー間のセッション状態を維持するためにセッション ID を保持します。ただし、Cookie には制限があります。この制限は Cookie のドメイン (通常は Web サイトのドメイン名に対応します) であり、ブラウザーが http リクエストを送信すると、すべての Cookie ではなく、そのドメインに一致する Cookie が自動的に送信されます。
この場合、理論的には、Web アプリケーション グループ内のすべてのサブシステムのドメイン名を 1 つのトップレベル ドメイン名 (「*.baidu.com」など) に統一して、その Cookie を設定できない可能性があります。初期の頃でも、多くのマルチシステム ログインでは、同じドメイン名で Cookie を共有するこの方法が使用されていました。 ただし、それが可能であるからといってそれが良いというわけではなく、Cookie の共有方法には多くの制限があります。まず第一に、アプリケーション グループのドメイン名を統一する必要があります。次に、アプリケーション グループ内の各システム (少なくとも Web サーバー) で使用されるテクノロジが同じである必要があります。そうでない場合は、Cookie のキー値 (Tomcat の場合は JSESSIONID) が同じである必要があります。 ) が異なり、セッションを維持できず、Java、php、.net システムなどの言語テクノロジ プラットフォームのログイン方法を国境を越えて実装できません。3 番目に、Cookie 自体が安全ではありません。 したがって、マルチシステムアプリケーショングループのログインを実現するための新しいログイン方法が必要です。それがシングルサインオンです 3. シングルサインオン シングルサインオンとは何ですか?シングル サインオンの正式名称はシングル サインオン (以下、SSO) です。複数システムのアプリケーション グループ内の 1 つのシステムにログインすると、再度ログインすることなく他のすべてのシステムで認証されることを意味します。シングル サインオンとシングル ログアウトが含まれます。 1. ログイン 単一システムのログインと比較して、SSO はユーザーのユーザー名、パスワード、その他のセキュリティ情報を受け入れることができます。ログイン入り口は提供せず、認証センターからの間接的な承認のみを受け入れます。間接認証はトークンを通じて実装され、SSO 認証センターはユーザーのユーザー名とパスワードが正しいことを確認し、次のジャンプ プロセスで認証トークンを各サブシステムに送信し、サブシステムがそのトークンを取得します。つまり、部分セッションの作成が許可されています。部分セッションのログイン方法は、単一システムのログイン方法と同じです。シングルサインオンの原理であるこのプロセスは、次の図で示されます
以下は、上図の簡単な説明です
- ユーザーは、システム1の保護されたリソースにアクセスします。 システム1ユーザーがログインしていないことを検出し、sso 認証センターにジャンプし、自分のアドレスをパラメーターとして使用します
- sso 認証センターは、ユーザーがログインしていないことを検出し、ユーザーをログイン ページに誘導します
- ユーザーは、ユーザー名とパスワードを入力してログイン アプリケーションを送信します
- sso 認証センターの検証 ユーザー情報、ユーザーと SSO 認証センターの間にグローバル セッションと呼ばれるセッションを作成し、同時に認証トークンを作成します
- SSO 認証センターは、トークンを使用して最初の要求アドレス (システム 1) にジャンプします
- システム 1 はトークンを取得し、SSO 認証センターに行き、トークンが有効かどうかを確認します
- SSO 認証センターはトークンを検証し、有効なものとして返します
- システム 1 はトークンを使用してユーザーとのセッション (部分セッションと呼ばれます) を作成し、保護されたリソースを返します
- ユーザーは保護されたリソースにアクセスしましたシステム 2
システム 2 は、ユーザーがログインしていないことを検出し、sso 認証センターにジャンプし、自分のアドレスをパラメーターとして使用します
sso 認証センターは、ユーザーがログインしていることを検出し、そのアドレスにジャンプして戻りますシステム 2 の認証を取得し、トークンを添付します
- システム 2 はトークンを取得し、SSO 認証センターに行き、トークンが有効かどうかを確認します
- SSO 認証センターはトークンを検証し、有効なものとして返します。 2
- システム 2 はトークンを使用して作成し、ユーザーのローカル セッションは保護されたリソースを返します
ユーザーが正常にログインすると、SSO 認証センターと各サブシステムとのセッションが確立されます。ユーザーが SSO 認証センターとの間で確立するセッションは、ローカル セッションと呼ばれます。ローカル セッションが確立されると、ユーザーはサブシステムの保護されたリソースにアクセスできなくなります。グローバルセッションとローカルセッションには以下の制約関係があります
- ローカルセッションが存在し、グローバルセッションが存在する必要があります
- グローバルセッションは存在しますが、ローカルセッションは必ずしも存在するとは限りません
- グローバル セッションが破棄され、ローカル セッションも破棄される必要があります
Blog Park、Baidu、csdn、Taobao などの Web サイトのログイン プロセスを通じて、シングル サインオンについての理解を深めることができます。ログインプロセス中のジャンプ URL とパラメーターに注意してください 2. ログアウト サブシステムでログアウトすると、すべてのサブシステム セッションが破棄されます。説明
SSO 認証センターはグローバル セッションのステータスを監視しています。グローバル セッションが破棄されると、リスナーは登録されているすべてのシステムにログアウト操作を実行するように通知します
以下は、上図
ユーザーがシステム 1 へのログアウト要求を開始します システム 1 は、ユーザーが確立したセッション ID に基づいてトークンを取得し、システム 1 が SSO 認証センターへのログアウト要求を開始します SSO 認証センターは、トークンが有効であることを確認し、グローバル セッションを破棄し、これを使用するすべてのユーザーを削除します トークン登録のシステム アドレス sso 認証センターは、すべての登録システムに対してログアウト要求を開始します 各登録システムsso 認証センターからログアウト要求を受け取り、ローカル セッションを破棄します sso 認証センターはユーザーをログイン ページに誘導します IV. シングル サインオンには、sso 認証センターと多くのサブシステムが関係します。サブシステムと sso 認証センターは、トークンの交換、トークンの検証、およびログアウト要求の開始のために通信する必要があるため、サブシステムは sso を統合する必要があります。クライアント、SSO 認証センターは、基本的にシングル サインオン プロセス全体です。 SSO クライアントとサーバー間の通信プロセス 以下の図を使用して、SSO 認証センターと SSO クライアント間の通信方法を説明します。ここでは、シンプルで使いやすい Web サービスである rpc を取り上げます。 5. 実装
完全なソースコードは提供されていませんが、原理を理解していれば、自分で実装できると思います。 sso はクライアント/サーバー アーキテクチャを採用しています。まず sso-client と sso-server によって実装される機能を見てみましょう (以下: sso 認証センター = sso-server)
sso-client
はログインしていないサブシステムをインターセプトします。ユーザー要求、sso 認証センターにジャンプします
sso 認証センターから送信されたトークンを受信して保存します
sso サーバーと通信してトークンの有効性を確認します
-
ローカルセッションを確立します
-
ユーザーのログアウト要求を傍受し、sso認証センターにログアウト要求を送信します
-
sso認証センターからログアウト要求を受信し、ローカルセッションを破棄します
-
sso-server
-
ユーザーのログイン情報を確認します
-
Cre食べたグローバルセッション + すべてのセッションからログアウト
次に、原則に従って SSO を段階的に実装してみましょう!
- 1. sso-clientはログイン以外のリクエストをインターセプトします Javaはサーブレット、フィルター、リスナーの3つの方法でリクエストをインターセプトします。 sso-client で新しい LoginFilter.java クラスを作成し、Filter インターフェースを実装し、doFilter() メソッドに未ログインのユーザーのインターセプトを追加します
- 12
- 34
- 5 6
- 78
- 910
1112
public void doFilter(ServletRequestリクエスト、ServletResponseレスポンス、FilterChainチェーン)throws IOException、ServletException { Ht tpServletRequest req = (HttpServletRequest) リクエスト; HttpServletResponse res = (HttpServletResponse) 応答;
HttpSession session = req.getSession();
if(session.getAttribute("isLogin")) {
chain.doFilter(request, response);
return; }
//ジャンプ先sso 認証センター
res.sendRedirect("sso-server-url-with-system-url");
}
|
2. sso-server が非ログイン要求をインターセプトします
sso- からのインターセプトclient sso認証センターの非ログインリクエストにジャンプし、ログインページにジャンプします。 このプロセスはsso-client
3と全く同じです。 sso-serverはユーザーのログイン情報を検証します
ユーザーはユーザー名とパスワードを入力します。ログインページでログインを要求し、sso 認証センターがユーザー情報を検証します。検証が成功すると、セッションのステータスが「ログイン中」とマークされます
124 。 56
@RequestMapping( "/login") |
public String login(String username, String password, HttpServletRequest req) { this.checkLoginInfo(username, パスワード); req.getSession( ).setAttribute("isLogin",true); return "success";}
|
4. sso-server は認可トークンを作成します 認可トークンはランダムな文字列です。繰り返されず、簡単ではない限り、生成方法は関係ありません。これが例です
1
String token = UUID.randomUUID().toString(); | |
5. sso クライアントがトークンを取得して検証します sso 認証センターにログインした後、サブシステムに戻り、トークンをアタッチします。検証のために sso 認証センターに送信し、LoginFilter.java の doFilter() に数行を追加します
12
3
4
5
6
7
8 9
10
11
//リクエストにはトークンパラメータが付属しています
| String token = req.getParameter("token");
if (token != null) {
// に移動しますsso 認証センターがトークンを検証します
booleanverifyResult = this.verify("sso-server-verify-url", token );
if(!verifyResult) {
res.sendRedirect("sso-server-url") );
return;
}
chain.doFilter(request, response); }
| verify()メソッドはhttpClientを使って実装されています。 httpClient については、公式ドキュメントを参照してください
12
HttpPost httpPost =new HttpPost("sso-server-verify-url-with-token");
| HttpResponse httpResponse = httpClient。 execute(httpPost);
| 6. sso サーバーは検証トークン要求を受信して処理します ユーザーが sso 認証センターに正常にログインすると、sso サーバーは認可トークンを作成し、トークンを保存します。 、sso-server はトークンを検証して、トークンが存在するかどうか、およびトークンの有効期限が切れているかどうかを確認します。トークンの検証が成功すると、sso-server は検証リクエストを SSO 認証センターに登録します (つまり、保存されます)。 トークンと登録システム アドレスは通常、キーと値のデータベース (redis など) に保存されます。Redis は、トークンの有効期間であるキーの有効期間を設定できます。 Redis はメモリ内で実行され、非常に高速です。sso サーバーはデータを保持する必要がありません。 トークンと登録システムのアドレスは、以下の図で説明されている構造を使用して Redis に保存できます。なぜこれらのシステムのアドレスを保存する必要があるのかと疑問に思われるかもしれません。保存しておかないと、ユーザーがSSO認証センターにログアウト要求を出し、SSO認証センターはグローバルセッションをログアウトしますが、どのシステムがこのグローバルセッションを使用したかがわかりません。独自のローカル セッションを確立するか、どのサブセッションを SSO 認証センターに送信する必要があるか、システムはローカル セッションをログアウトするためのログアウト要求を送信します
7。部分セッション
トークンの検証が成功すると、sso-client は現在の部分セッションを「ログイン済み」としてマークし、LoginFilter .java を変更して、数行を追加します
12
3
if (verifyResult) { session.setAttribute("isLogin",true); |
}
sso-client は、現在のセッション ID をトークンにバインドする必要があります。これは、このセッションのログイン ステータスがトークンに関連していることを示します。保存されたデータは、送信されたログアウト リクエストの処理に使用されます。 sso 認証センターによる
8. ログアウト プロセス
ユーザーは、「logout」パラメーターを含むリクエスト (ログアウト リクエスト) をサブシステムに送信し、sso クライアント インターセプターがリクエストをインターセプトし、sso 認証へのログアウト リクエストを開始します。 center
1 2
3
4
|
String logout = req.getParameter("logout");
if (logout != null) {
this.ssoServer.logout (トークン);
}
|
sso 認証センターも同じ方法を使用して、sso クライアント要求がログアウト要求 (「logout」パラメーターを使用) であることを識別し、sso 認証センターはログアウトします。グローバルセッション
1
2
3
4
5
6
7
8
|
@RequestMapping("/logout")
public String logout(HttpServletRequest req) {
HttpSession session = req. getSession();
if(session != null) {
session.invalidate();//Trigger LogoutListener
}
return "redirect:/";
}
|
sso 認証センターにはグローバル セッション モニターがあります。グローバル セッションがログアウトされると、登録されているすべてのシステムにログアウトするように通知されます
1
2
3
4
5
6
7
8
|
public class LogoutListenerimplementsHttpSessionListener {
// httpClient を通じてすべての登録システムにログアウト リクエストを送信します
}
}
関連する推奨事項:
|
シングル サインオン Cookie 分析とPHPでの実装
シングルサインオンの原理と簡単な実装
SSOシングルサインオンのPHP実装方法(Laravelフレームワーク)
|
|
以上がSSO シングル サインオンの原理を説明する例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。