Tomcat 与 SSO
1.概述
在本文中,我们将了解 Tomcat 服务器基础知识、它的工作原理以及如何启用 Tomcat 的单点登录 ( SSO ) 功能。我们将探索 Tomcat 服务器和 Web 应用程序所需的配置。
2.Tomcat架构
构成 Catalina servlet 容器的主要部分是包含定义连接器的服务和由主机构建的引擎的服务器,最后,这些主机将包含上下文或 Web 应用程序。
连接器侦听客户端的请求并发送回响应。在 Tomcat 10 中,我们可以找到以下协议的连接器:HTTP/1.1 、HTTP/2 和AJP 。
引擎将处理连接器收到的请求并生成输出。它将包含一个 处理管道 ,这是一个进程链,每个请求都会执行以产生响应。这些过程就是 Tomcat 的阀门 。例如,Tomcat 上的 SSO 是作为阀门实现的。
之后,我们找到将定义将网络名称与服务器相关联的虚拟主机的主机。这是定义 SSO 阀的级别,因此主机的所有上下文都将位于 SSO 之下。
最后,我们将拥有与主机关联的上下文元素。这些上下文是将在服务器上运行的 Web 应用程序。上下文必须遵循 servlet 规范 2.3 或更高版本。
3. Tomcat 单点登录
Tomcat 在必须在主机级别配置的 Valve 中实现单点登录功能。它的工作方式是 SSO 阀门将存储用户凭据并在需要时传递它们,因此用户无需再次登录。
SSO 阀需要满足以下要求:
- Realm 或“用户数据库”必须由虚拟主机下的所有 Web 应用程序共享。
- Web 应用程序身份验证机制必须是标准身份验证器之一:Basic 、Digest 、Form 、SSL 或SPNEGO 。
- 当客户端请求受保护的资源时,服务器将执行 Web 应用程序的身份验证机制。
- 服务器将使用经过身份验证的用户的角色访问虚拟主机下的 Web 应用程序的受保护资源,而无需再次登录。
- 当用户退出 Web 应用程序时,服务器将使所有 Web 应用程序中的用户会话无效。
- 客户端必须接受 cookie。cookie 存储将请求与用户凭据相关联的令牌。
3.1.Tomcat 服务器配置
在服务器端,我们需要配置SingleSignOn阀门和领域或“用户数据库”。这些配置在 Tomcat 安装的 conf 文件夹下的 server.xml 文件中。要添加 SSO 阀,我们需要取消注释以下行:
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
对于本文的示例,我们将依赖默认配置的 Realm,我们只需要将用户添加到数据库中。领域定义如下所示:
<Realm
className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
此配置使用全局 JNDI 资源来定义用户数据库的来源:
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
该资源将实例化一个 org.apache.catalina.UserDatabase 类型的对象,并将使用工厂类org.apache.catalina.users.MemoryUserDatabaseFactory从 tomcat-users.xml 文件中填充它 。
最后,在这里我们看看如何添加一个具有文章示例所需的管理员角色的用户。我们需要修改tomcat-users.xml文件:
<tomcat-users xmlns="http://tomcat.apache.org/xml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
version="1.0">
<role rolename="admin"/>
<user username="demo" password="demo" roles="admin"/>
</tomcat-users>
3.2. Web 应用程序配置
一旦我们配置了服务器,让我们通过每个 servlet 的 WEB-INF 文件夹中的 web.xml 配置文件来配置 servlet。
所有需要 SSO 的 Web 应用程序都必须具有受保护的资源并使用一种 Tomcat 身份验证方法。正如 Servlet API 规范 2.3 中定义的那样,Web 应用程序的身份验证机制在web-app元素内的 login-config 元素中定义。此元素将包含需要使用以下值之一的身份验证方法表单:BASIC、DIGEST、FORM 或 CLIENT-CERT。每种身份验证方法都有不同的配置,但我们将在Tomcat Web 应用程序配置 部分仅讨论 DIGEST 和 FORM 身份验证方法。
要完成 Web 应用配置,我们需要设置保护区。在 web-app 元素下的 web.xml 文件中,我们可以根据需要添加任意数量的安全约束元素。每个安全约束都定义了受保护资源的 URL 模式,并将设置允许的角色。此外,我们需要为所有角色定义安全角色元素,并且它们必须与 tomcat-users.xml 文件中的定义相匹配。我们将在下一节中看到一个示例。
4. 示例认证机制
现在我们知道如何配置 Web 应用程序,让我们看两个示例:Ping 和 Pong。我们选择了不同的身份验证机制来证明 SSO 可以很好地与不同的机制配合使用。
4.1. Ping 认证机制
在 ping web 应用程序中,我们使用 FORM 身份验证方法。FORM认证方式需要登录表单,网页登录失败。例如,当我们想要将登录页面自定义为 Web 应用程序时,此方法将很有用,配置如下所示:
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/logging.html</form-login-page>
<form-error-page>/logging_error.html</form-error-page>
</form-login-config>
</login-config>
**登录页面必须遵循 servlet 规范 2.3 的登录表单注释中定义的一些严格规则,**因为我们既不能选择表单名称,也不能选择输入字段。它们必须是j_security_check、 j_username和j_password。这是为了实现登录表单与各种资源一起使用,并且无需在服务器中配置出站表单的操作字段。在这里,我们可以看到它必须是什么样子的示例:
<!DOCTYPE html>
<html>
<head>
<title>Ping - Login</title>
</head>
<body>
<form method="post" action="j_security_check">
<table >
<tr>
<td>User name: </td>
<td><input type="text" name="j_username" size="20"/></td>
</tr>
<tr>
<td>Password: </td>
<td><input type="password" name="j_password" size="20"/></td>
</tr>
</table>
<p></p>
<input type="submit" value="Submit"/>
<input type="reset" value="Reset"/>
</form>
</body>
</html>
为了理解服务器收到来自 FORM 认证的 Web 应用的受保护资源的请求时会发生什么,让我们总结一下这种认证机制的流程。
首先,客户端请求一个受保护的资源。如果服务器不包含有效的 SSO 会话 ID,则服务器会将客户端重定向到日志记录表单。用户填写表单并将其凭据发送到服务器后,身份验证机制将启动。
用户认证成功后,服务器会检查用户的角色,如果安全约束至少允许其中之一,服务器会将客户端重定向到请求的 URL。在另一种情况下,服务器会将客户端重定向到错误页面。
4.2. 认证机制
在 Pong Web 应用程序中,我们使用 DIGEST 身份验证机制,配置将如下所示:
<login-config>
<auth-method>DIGEST</auth-method>
</login-config>
**DIGEST 身份验证机制流程类似于 BASIC 身份验证:**当客户端请求受保护的资源时,服务器返回一个对话框以请求用户凭据。如果认证成功,则服务器返回请求的资源,但在另一种情况下,服务器再次发送认证对话框。
尽管 DIGEST 和 BASIC 身份验证方法相似,但有一个重要区别:密码保留在服务器中。
4.3. Web 应用安全约束配置
在这一点上,我们不打算区分 Ping 和 Pong。尽管它们具有不同值的元素,但配置的重要部分在两个应用程序中将保持不变:
<security-constraint>
<display-name>Ping Login Auth</display-name>
<web-resource-collection>
<web-resource-name>PingRestrictedAccess</web-resource-name>
<url-pattern>/private/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
安全约束定义私有文件夹下的所有内容都是受保护的资源,并且还定义了需要具有管理员角色才能访问资源。
5. 运行示例
现在我们需要安装一个Tomcat 10 服务器,按照文章前面所示调整配置,将 Ping 和 Pong web 应用程序放在 Tomcat 的 web 应用程序文件夹下。
一旦服务器启动并运行,并且两个应用程序都已部署,请求资源 http://localhost:8080/ping/private 。服务器将显示登录身份验证,因为我们没有登录:
然后我们需要引入Tomcat服务器配置 部分配置的凭据并提交表单。如果服务器验证了凭据,那么我们将看到一个网页,其中包含指向 pong 私有部分的链接:
如果服务器不验证访问,我们将看到登录错误页面。
成功登录 Ping 应用程序后,我们可以看到 SSO 机制正在运行,单击指向 pong 私有部分的链接。如果会话已经处于活动状态,服务器将发送 Pong 的受保护资源,而无需我们再次登录。
最后,我们可以检查会话过期后,服务器会再次显示登录页面。我们可以通过等待几分钟并单击指向 ping 私人部分的链接来做到这一点。