優れたオープン ソース シングル サインオン プロジェクト分散シングル サインオン フレームワーク。一度ログインするだけで、相互に信頼できるすべてのアプリケーション システムにアクセスできます。「軽量、分散、クロスドメイン、Cookie+Token対応、Web+APP対応」という特徴があります。
XXL-SSO は、分散シングル サインオン フレームワークです。一度ログインするだけで、相互に信頼できるすべてのアプリケーション システムにアクセスできます。「軽量、分散、クロスドメイン、Cookie+Token対応、Web+APP対応」という特徴があります。オープンソースになり、箱から出してすぐに使用できます。
XXL-JOB に精通している場合、これは非常に人気のある分散タスク スケジューリング プラットフォームです。しかし実際には、著者は XXL-SSO という非常に優れたオープン ソース プロジェクトも持っており、どちらも多くのスターを獲得しています。
1. sso への高速アクセス
1. xxl-ssoの特徴
簡潔:APIが直感的かつ簡潔で、すぐに始められる
軽量:環境への依存が少なく、導入やアクセスのコストが低い
シングルサインオン:必要なものはたった一つ一度ログインすると、相互に信頼できるすべてのアプリケーション システムにアクセスできます
分散型: SSO 認証センターのアプリケーションへのアクセス、分散展開のサポート
HA: サーバー側とクライアント側の両方がクラスター展開をサポートし、システムの可用性を向上させます クロス
ドメイン: クロスドメインをサポートしますSSO 認証センターへのアプリケーション アクセス
Cookie+Token サポート: Cookie に基づくサポートと Token の 2 つのアクセス方法に基づくサポート、および両方の提供 サンプル プロジェクト
Web+APP サポート: Web および APP アクセスのサポート
リアルタイム: システムのログインとログアウトのステータス、すべてのサーバーとクライアントは、リアルタイムの
CS 構造を共有します: サーバー「認証センター」とクライアント「保護されたアプリケーション」を含む CS 構造に基づきます
パスワードの記憶: パスワードが記憶されていない場合、ブラウザを閉じるとログイン ステータスが無効になります。パスワードを記憶すると、ログイン状態を自動的に延長することができます. カスタム延長時間に基づいて, 原則それは無期限に延長することができます. パスの除外: カスタムの
複数の除外パスをサポートし、Ant 式をサポートし、実行するパスを除外するために使用されます. SSO クライアントでフィルタリングする必要はありません
2. 環境
JDK: 1.7+
Redis: 4.0+
3. ソースアドレス
github: https://github.com/xuxueli/xxl-sso
gitee: https://gitee.com/xuxueli0323/xxl-sso
4. プロジェクト構造の説明
- xxl-sso-server: 中央認証サービス、サポート クラスター
- xxl-sso-core: クライアント側の依存関係
- xxl-sso-samples: シングル サインオン クライアント アクセス サンプル プロジェクト
- xxl-sso-web-sample-springboot: Cookie アクセス方式に基づく、ユーザー ブラウザ アクセス用、springboot バージョン
- xxl-sso-token-sample-springboot: Token アクセス方式をベースに、アプリや Cookie が禁止されているなど、Cookie を使用できないシナリオで使用されることが多い
5. 構成図
申請システム:sso-webシステム(ポート8081)、sso-webシステム(ポート8082)(ログインが必要なシステム)
SSO クライアント: ログイン、終了 (アプリケーション システムによって参照される独立した jar パッケージ)
SSOサーバー:login(ログインサービス)、login status(ログイン状態確認・ログイン情報照会サービス)、logout(ユーザーログアウトサービス)
データベース: ユーザー アカウント情報を保存します (通常は Mysql が使用され、現在のプロジェクトでは単純化のためにデータベースへのクエリは行われません)
キャッシュ: ユーザーのログイン情報を保存します (Redis を使用)
2. XXL-SSO フレームワークへのクイック アクセス
1. 認証センター (sso-server) の展開は、
構成ファイルを変更するだけで済みます. 構成ファイルの場所: application.properties
## 配置redis
xxl.sso.redis.address=redis://118.31.224.65:6379
## 登录态有效期窗口,默认24H,当登录态有效期窗口过半时,自动顺延一个周期
xxl.sso.redis.expire.minute=1440
2. Deploy the "Single Sign-On Client Access Sample Project"
here. ここでは、SSO にアクセスする必要があるシステムを指します. 現在のプロジェクトには、xxl-sso-web-sample-springboot と xxl-sso- の 2 つのサンプル プロジェクトがあります。 token-sample-springboot 、ここでは例として sso-web を取り上げます。
1)、maven の依存関係
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-sso-core</artifactId>
<version>${最新稳定版}</version>
</dependency>
2) XxlSsoFilter を構成する
参照コード: com.xxl.sso.sample.config.XxlSsoConfig
@Bean
public FilterRegistrationBean xxlSsoFilterRegistration() {
// xxl-sso, redis init
JedisUtil.init(xxlSsoRedisAddress);
// xxl-sso, filter init
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setName("XxlSsoWebFilter");
registration.setOrder(1);
registration.addUrlPatterns("/*");
registration.setFilter(new XxlSsoWebFilter());
registration.addInitParameter(Conf.SSO_SERVER, xxlSsoServer);
registration.addInitParameter(Conf.SSO_LOGOUT_PATH, xxlSsoLogoutPath);
return registration;
}
application.propertiesの変更
## 中央认证服务地址
xxl.sso.server=http://ssoserver.com:8080/xxl-sso-server
## 退出接口
xxl.sso.logout.path=/logout
## 排除走sso的接口
xxl-sso.excluded.paths=/excludedUrl
## redis地址
xxl.sso.redis.address=redis://118.11.214.65:6379
3. 迅速な検証
1. ホスト ファイルの変更
ホスト ファイルの変更: ドメイン名で認証センターにアクセスし、クロスドメインおよびオンラインの実環境をシミュレートします。
127.0.0.1 ssoserver.com
127.0.0.1 webb.com
127.0.0.1 weba.com
2. 「xxl-sso-server」と「xxl-sso-web-sample-springboot」をそれぞれ実行するプロジェクト
を起動 シングルサインオンを確認するために、ここでは sso-web を 2 回起動する必要がありますが、1 回はポート 8081 と 1 回は 8082 ポートです。
## 1、SSO认证中心地址:
http://ssoserver.com:8080/xxl-sso-server
## 2、Client01应用地址:
http://weba.com:8081/xxl-sso-web-sample-springboot/
## 3、Client02应用地址:
http://webb.com:8082/xxl-sso-web-sample-springboot/
3.
SSO ログイン プロセスを確認する
通常、ログインプロセスは次のとおりです。
1.「Client01アプリケーションアドレス」にアクセスすると、「SSO認証センターアドレス」のログインインターフェースに自動でリダイレクトされます
2. ログインに成功すると、自動的に「Client01 アプリケーションアドレス」にリダイレクトされ、ログイン状態に切り替わります
3. このとき、ログインせずに「Client02 アプリケーションアドレス」にアクセスすると、自動的に「Client02 アプリケーションアドレス」に切り替わりますログイン状態
明らかに、Client01 が正常にログインした後、Client02 は再度ログインしなくてもアクセスできます。
SSO ログアウト プロセス
通常の状況では、ログアウト プロセスは次のとおりです。
1.「Client01アプリケーションアドレス」に設定された「ログアウトパス」にアクセスすると、「SSO認証センターアドレス」に自動リダイレクトされ、ログイン状態から自動ログアウトされます
。アドレス」、また自動的にログアウト状態になります
4. コア コード分析
1. SSO クライアント (sso-core) インターセプターは
、主に sso インターセプターのプロセスに依存します。
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
// 获取当前请求接口
String servletPath = req.getServletPath();
// 1、是否是排除 不走sso的接口 如果是直接放行
if (excludedPaths != null && excludedPaths.trim().length() > 0) {
for (String excludedPath : excludedPaths.split(",")) {
String uriPattern = excludedPath.trim();
// 支持ANT表达式
if (antPathMatcher.match(uriPattern, servletPath)) {
// excluded path, allow
chain.doFilter(request, response);
return;
}
}
}
// 2、是否是退出登录接口
if (logoutPath != null
&& logoutPath.trim().length() > 0
&& logoutPath.equals(servletPath)) {
// 2.1删除当前请求客户端的cookie
SsoWebLoginHelper.removeSessionIdByCookie(req, res);
// 2.2重定向到sso认证服务的 退出接口
String logoutPageUrl = ssoServer.concat(Conf.SSO_LOGOUT);
res.sendRedirect(logoutPageUrl);
return;
}
// 3、校验用户(是否存在,是否过期) 这个方法下面在展开
XxlSsoUser xxlUser = SsoWebLoginHelper.loginCheck(req, res);
// 4、令牌校验失败
if (xxlUser == null) {
//获取当前请求地址
String link = req.getRequestURL().toString();
// 重定向到sso认证服务的 登录接口
String loginPageUrl = ssoServer.concat(Conf.SSO_LOGIN)
+ "?" + Conf.REDIRECT_URL + "=" + link;
res.sendRedirect(loginPageUrl);
return;
}
// ser sso user
request.setAttribute(Conf.SSO_USER, xxlUser);
// 已经登录 放行
chain.doFilter(request, response);
return;
}
上記の loginCheck メソッドを見てください。
/**
* 令牌校验
*
* @return 用户信息
*/
public static XxlSsoUser loginCheck(HttpServletRequest request, HttpServletResponse response){
//去cookie去获取xxl_sso_sessionid 其实就是之前原理篇说的token,只是名称叫法不同
String cookieSessionId = CookieUtil.getValue(request, Conf.SSO_SESSIONID);
// 这里去redis中获取用户信息 有可能获取不到。这个方法就不粘贴了 这里有三种情况
//1、cookieSessionId为空 那么直接返回null
//2、cookieSessionId不为空,但在redis获取不到用户信息,因为存在其它系统退出后 redis删除了
//3、redis获取到了用户信息,但超过有效期了 依旧返回null
XxlSsoUser xxlUser = SsoTokenLoginHelper.loginCheck(cookieSessionId);
if (xxlUser != null) {
return xxlUser;
}
// 如果获取不到 所以已经在其它系统退出登录了 那删除cookie中的xxl_sso_sessionid
SsoWebLoginHelper.removeSessionIdByCookie(request, response);
//如果是 sso登录成功后 回调过来的 这个时候在这里是可以获取到xxl_sso_sessionid的
String paramSessionId = request.getParameter(Conf.SSO_SESSIONID);
xxlUser = SsoTokenLoginHelper.loginCheck(paramSessionId);
if (xxlUser != null) {
CookieUtil.set(response, Conf.SSO_SESSIONID, paramSessionId, false); /
return xxlUser;
}
return null;
}
2. 認証サーバー (sso-server) ログインインターフェース
/**
* sso认证中心 登录接口
*/
@RequestMapping(Conf.SSO_LOGIN)
public String login(Model model, HttpServletRequest request, HttpServletResponse response) {
// 同样的 该判断sso上有没有全局会话
XxlSsoUser xxlUser = SsoWebLoginHelper.loginCheck(request, response);
//如果 其它系统登录成功过 这个就不回为null 直接再带上xxl_sso_sessionid=xxx 重定向到之前接口
//也不用在登录了
if (xxlUser != null) {
// success redirect
String redirectUrl = request.getParameter(Conf.REDIRECT_URL);
if (redirectUrl!=null && redirectUrl.trim().length()>0) {
String sessionId = SsoWebLoginHelper.getSessionIdByCookie(request);
String redirectUrlFinal = redirectUrl + "?" + Conf.SSO_SESSIONID + "=" + sessionId;;
return "redirect:" + redirectUrlFinal;
} else {
return "redirect:/";
}
}
//只有全局会话不存在 才会跳转登录页面
model.addAttribute("errorMsg", request.getParameter("errorMsg"));
model.addAttribute(Conf.REDIRECT_URL, request.getParameter(Conf.REDIRECT_URL));
return "login";
}
3. 認証サーバー (sso-server) 出口インターフェース
@RequestMapping(Conf.SSO_LOGOUT)
public String logout(HttpServletRequest request, HttpServletResponse response, RedirectAttributes redirectAttributes) {
// 退出操作
SsoWebLoginHelper.logout(request, response);
// 跳转到登录页
redirectAttributes.addAttribute(Conf.REDIRECT_URL, request.getParameter(Conf.REDIRECT_URL));
return "redirect:/login";
}
logout メソッドの機能を見てみましょう
public static void logout(HttpServletRequest request,
HttpServletResponse response) {
String cookieSessionId = CookieUtil.getValue(request, Conf.SSO_SESSIONID);
if (cookieSessionId==null) {
return;
}
//1、删除全局缓存 redis中 清除cookieSessionId,这样其它系统在令牌校验的时候 会失败。即一处退出,处处退出。
String storeKey = SsoSessionIdHelper.parseStoreKey(cookieSessionId);
if (storeKey != null) {
SsoLoginStore.remove(storeKey);
}
//2、清除全局会话
CookieUtil.remove(request, response, Conf.SSO_SESSIONID);
}
コアコード全体のロジックはここにあり、実際、前の記事の理論と組み合わせると、理解するのはまったく複雑ではありません。