[Tomcat源码系列] 扩展
一、 Realm/ HTTP认证
1)Realm
Realm提供了Web认证用户和角色信息的存储机制,如下是Tomcat关于Realm的说明我们看看Realm的接口定义
public interface Realm { public Container getContainer(); public void setContainer(Container container); public String getInfo(); public void addPropertyChangeListener(PropertyChangeListener listener); public Principal authenticate(String username, String credentials); public Principal authenticate(String username, byte[] credentials); public Principal authenticate(String username, String digest, String nonce, String nc, String cnonce, String qop, String realm, String md5a2); public Principal authenticate(X509Certificate certs[]); public void backgroundProcess(); public SecurityConstraint [] findSecurityConstraints(Request request, public boolean hasResourcePermission(Request request, Response response, SecurityConstraint [] constraint, Context context) throws IOException; public boolean hasRole(Principal principal, String role); public boolean hasUserDataPermission(Request request, Response response, SecurityConstraint []constraint) throws IOException; public void removePropertyChangeListener(PropertyChangeListener listener); }
Tomcat提供了多种的Realm实现,实现代码比较简单
- org.apache.catalina.realm.DataSourceRealm:Implmentation of Realm that works with any JDBC JNDI DataSource.See the JDBCRealm.howto for more details on how to set up the database and for configuration options
- org.apache.catalina.realm.JAASRealm:Implmentation of Realm that authenticates users via the Java Authentication and Authorization Service (JAAS).
- org.apache.catalina.realm.JDBCRealm:Implmentation of <b>Realm</b> that works with any JDBC supported database. See the JDBCRealm.howto for more details on how to set up the database and for configuration options.
- org.apache.catalina.realm.JNDIRealm:Implementation of <strong>Realm</strong> that works with a directory server accessed via the Java Naming and Directory Interface (JNDI) APIs.
- org.apache.catalina.realm.MemoryRealm:Simple implementation of <b>Realm</b> that reads an XML file to configure the valid users, passwords, and roles.
- org.apache.catalina.realm.UserDatabaseRealm:Implementation of Realm that is based on an implementation of UserDatabase made available through the global JNDI resources configured for this instance of Catalina.(通过UserDatabase接口来获取认证信息,默认配置这个,见{tomcat}/conf/tomcat-users.xml)
2)HTTP认证 关于HTTP认证可参见《HTTP认证及其在Web平台中的实现》,Tomcat通过Realm实现HTTP认证用户/角色信息的存储。Tomcat的HTTP认证实现以Valve的方式提供的(见之前关于pipeline的说明,需要注意的是,这个Valve不需要显式地配置,默认ContextConfig会根据web.xml设置的信息自动注册一个认证实现),每种实现会实现org.apache.catalina.Authenticator接口(空接口)
public interface Authenticator { }
默认Tomcat提供了如下的实现,代码比较简单,可同时参见Realm的实现
- BASIC=org.apache.catalina.authenticator.BasicAuthenticator
- CLIENT-CERT=org.apache.catalina.authenticator.SSLAuthenticator
- DIGEST=org.apache.catalina.authenticator.DigestAuthenticator
- FORM=org.apache.catalina.authenticator.FormAuthenticator
- NONE=org.apache.catalina.authenticator.NonLoginAuthenticator
如下是tomcat默认提供的manager的web.xml中关于HTTP认证部分的配置
<security-constraint> <web-resource-collection> <web-resource-name>HTMLManger and Manager command</web-resource-name> <url-pattern>/jmxproxy/*</url-pattern> <url-pattern>/html/*</url-pattern> <url-pattern>/list</url-pattern> <url-pattern>/expire</url-pattern> <url-pattern>/sessions</url-pattern> <url-pattern>/start</url-pattern> <url-pattern>/stop</url-pattern> <url-pattern>/install</url-pattern> <url-pattern>/remove</url-pattern> <url-pattern>/deploy</url-pattern> <url-pattern>/undeploy</url-pattern> <url-pattern>/reload</url-pattern> <url-pattern>/save</url-pattern> <url-pattern>/serverinfo</url-pattern> <url-pattern>/status/*</url-pattern> <url-pattern>/roles</url-pattern> <url-pattern>/resources</url-pattern> <url-pattern>/findleaks</url-pattern> </web-resource-collection> <auth-constraint> <!-- NOTE: This role is not present in the default users file --> <role-name>manager</role-name> </auth-constraint> </security-constraint> <!-- Define the Login Configuration for this Application --> <login-config> <auth-method>BASIC</auth-method> <realm-name>Tomcat Manager Application</realm-name> </login-config> <!-- Security roles referenced by this web application --> <security-role> <description> The role that is required to log in to the Manager Application </description> <role-name>manager</role-name> </security-role>
二、 Manager/Cluster
1.Manager
Manager接口实现了对Session的管理,看看Tomcat中关于Manager的定义org.apache.catalina.session.StandardManager是默认的Manager实现,在内存中维持Session信息,并支持简单地将 Session持久化到文件中,以支持在Tomcat重启后Session信息不会全部丢失(注意,只有通过正确的shutdown,Session信息才会被正确持久化)我们可以通过扩展Manager来自定制对Session的管理(譬如,我们可以扩展使用memcached来存储session数据),除StandardManager,Tomcat还提供了如下的Session实现
- org.apache.catalina.session.PersistentManager:支持将不活跃的Session数据持久化,只维持部分Session信息在内存,一方面支持服务重启而Session不丢失,一方面支持错误恢复,即使服务非正常重启也能够保证Session信息不丢失,另一方面只须要在内存中维持部分的Session信息。其中数据的持久化是一种策略,支持文件、数据库等方式的持久化,关于持久化策略,具体参见org.apache.catalina.Store及其实现org.apache.catalina.session.FileStore和org.apache.catalina.session.JDBCStore。我们可以通过使用共享文件/数据库的方式, PersistentManager+FileStore/ JDBCStore来实现Session数据的集群,需要注意的是,PersistentManager只会当Session Idle时才会持久化Session数据,因此不是实时复制的
- org.apache.catalina.ha.session.SimpleTcpReplicationManager:ha Session实现,使用全复制的方式,在请求处理完毕之后,如果Session有变化,则将整个Session数据复制给其他的集群节点
- org.apache.catalina.ha.session.DeltaManager;ha Session实现,采用只复制变更部分的方式,在请求处理完毕之后,将Session有变更的数据部分复制给其他的节点
- org.apache.catalina.ha.session.BackupManager:ha Session实现,与DeltaManager复制方式一样,但不是复制给所有节点,而是只复制给一个备份节点
2.Cluster关于Cluster的详情可参见http://tomcat.apache.org/tomcat-6.0-doc/cluster-howto.html ,Cluster是Manager的创建工厂,Cluster的接口非常简单,如下
public interface Cluster { public String getInfo(); public String getClusterName(); public void setClusterName(String clusterName); public void setContainer(Container container); public Container getContainer(); public void setProtocol(String protocol); public String getProtocol(); public Manager createManager(String name); public void registerManager(Manager manager); public void removeManager(Manager manager); public void backgroundProcess(); }
Cluster的实现只有一种org.apache.catalina.ha.tcp.SimpleTcpCluster,通过如下的配置范例,我们可以大概了解Cluster的主要结构,关于详细的实现,可以参见org.apache.catalina.ha包,代码相对比较独立,初始化和请求处理机制跟Tomcat机制类似,我们在前面中已有介绍。
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8"> <Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true"/> <Channel className="org.apache.catalina.tribes.group.GroupChannel"> <Membership className="org.apache.catalina.tribes.membership.McastService" address="228.0.0.4" port="45564" frequency="500" dropTime="3000"/> <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" port="4000" autoBind="100" selectorTimeout="5000" maxThreads="6"/> <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"> <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/> </Sender> <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/> <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/> </Channel> <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/> <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/> <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" tempDir="/tmp/war-temp/" deployDir="/tmp/war-deploy/" watchDir="/tmp/war-listen/" watchEnabled="false"/> <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/> <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/> </Cluster>