Tomcat如何使用Realm
omcat 6 —— Realm域管理
本篇来源于官方文档,但不仅仅是翻译,其中不乏网上搜索的资料与自己的理解。
如有错误,请予指正。
什么是Realm
首先说一下什么是Realm,可以把它理解成“域”,也可以理解成“组”,因为它类似 类Unix系统 中组的概念。
Realm域提供了一种用户密码与web应用的映射关系。
因为tomcat中可以同时部署多个应用,因此并不是每个管理者都有权限去访问或者使用这些应用,因此出现了用户的概念。但是想想,如果每个应用都去配置具有权限的用户,那是一件很麻烦的事情,因此出现了role这样一个概念。具有某一角色,就可以访问该角色对应的应用,从而达到一种域的效果。
参考上面的图:
每个用户我们可以设置不同的角色(在tomcat-users.xml中配置),
每个应用中会设定可以访问的角色(在web.xml中配置),
当tomcat启动后,就会通过Realm进行验证(在server.xml中配置),通过验证才可以访问该应用,
从而达到角色安全管理的作用。
理解server.xml
在tomcat中,要理解其架构设计,可以参考下面的图,该图是从《Apahce tomcat高级配置》一书中扒下来的。
参考上面的图解释下:
server:即服务器,每个tomcat程序启动后,就是一个server。
service:这是一种抽象的服务,通常是在日志或者管理时使用这样一个概念。它把连接器和处理引擎结合在一起。
connector:用于处理连接和并发,通常包括两种方式HTTP和AJP。HTTP是用于网页地址栏http这种访问方式;AJP一般用于搭配Apache服务器。
engine:处理引擎,所有的请求都是通过处理引擎处理的。
host:虚拟主机,用于进行请求的映射处理。每个虚拟主机可以看做独立的请求文件。
realm:用于配置安全管理角色,通常读取tomcat-uesrs.xml进行验证。
context:上下文,对应于web应用。
有了上面的概念的理解,就可以简单的想象一下tomcat的处理过程:
大体过程如下:
0 首先请求发送给服务器;
1 服务器使用相应的服务进行处理。
2 先通过不同的连接器请求后发送给处理引擎。
3 处理引擎通过对虚拟主机的分析,发送给相应的虚拟主机。
4 虚拟主机使用相应的应用进行相应。
简言之,就是请求会先发送到连接器,连接器转给处理引擎进行处理。
再看看默认的server.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <Server port="8005" shutdown="SHUTDOWN"> <Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/> <Listener className="org.apache.catalina.core.JasperListener"/> <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener"/> <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/> <GlobalNamingResources> <Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/> </GlobalNamingResources> <Service name="Catalina"> <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/> <Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/> <Engine defaultHost="localhost" name="Catalina"> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true" xmlNamespaceAware="false" xmlValidation="false"> <Context docBase="E:\software\Tomcat6.0.14\apache-tomcat-6.0.14\wtpwebapps\firstFilter" path="/firstFilter" reloadable="true" source="org.eclipse.jst.jee.server:firstFilter"/> <!-- 自己添加的 --> </Host> </Engine> </Service> </Server>
去掉注释部分可以观察的更方便,可以看到默认情况下,Realm的配置位置是在Engine标签内部,并且使用的是UserDatabase的方式。其他的方式会在下面部分说明。
其中Realm的不同位置也会影响到它作用的范围。
1 在<Engine>元素内部 —— Realm将会被所有的虚拟主机上的web应用共享,除非它被<Host>或者<Context>元素内部的Realm元素重写。
2 在<Host>元素内部 —— 这个Realm将会被本地的虚拟主机中的所有的web应用共享,除非被<Context>元素内部的Realm元素重写。
3 在<Context>元素内部 —— 这个Realm元素仅仅被该Context指定的应用使用。
Realm获取用户信息方式
目前tomcat支持多种Realm管理方式,即支持多种方式来读取用户信息进行验证。参考如下:
1 JDBCRealm 用户授权信息存储于某个关系型数据库中,通过JDBC驱动获取信息验证
2 DataSourceRealm 用户授权信息存储于关于型数据中,通过JNDI配置JDBC数据源的方式获取信息验证
3 JNDIRealm 用户授权信息存储在基于LDAP的目录服务的服务器中,通过JNDI驱动获取并验证
4 UserDatabaseRealm 默认的配置方式,信息存储于XML文档中 conf/tomcat-users.xml
5 MemoryRealm 用户信息存储于内存的集合中,对象集合的数据来源于xml文档 conf/tomcat-users.xml
6 JAASRealm 通过JAAS框架访问授权信息
配置过程
参考下默认的配置server.xml中,可以看到默认情况下使用的就是UserDatabaseRealm的方式:
上图中的代码配置了UserDatabase的目录文件,为conf/tomcat-users.xml
上图中的代码配置使用的Realm方式。
上面是tomcat-users.xml中的配置内容。
3 在应用的web.xml中配置其访问角色以及安全限制的内容
关于Realm域的使用,一般都是用来管理一些安全性要求很高的应用,最常见的就是manager应用。
manager应用用于在不停止tomcat的情况下部署或者停止某些应用,处于安全考虑,默认情况下时不能访问manager应用的,因此需要现在tomcat-users.xml中添加用户以及相应的角色,才能访问。
参考下tomcat中manager应用的角色配置,观察其web.xml配置文件,可以找到下面这段:
<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>/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> </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>
其中role-name就定义了可以访问的角色。
其他内容中上面定义了限制访问的资源,下面的Login-config比较重要。
它定义了验证的方式,BASIC就是基本的弹出对话框输入用户名密码。还是DIGEST方式,这种方式会对网络中的传输信息进行加密,更安全。
JDBCRealm配置过程
1 在web.xml中添加以下代码
<security-constraint> <display-name>Example Security Constraint</display-name> <web-resource-collection> <web-resource-name>Protected Area</web-resource-name> <!-- Define the context-relative URL(s) to be protected --> <url-pattern>/jsp/bookstore.jsp</url-pattern> <!-- If you list http methods, only those methods are protected --> </web-resource-collection> <auth-constraint> <!-- Anyone with one of the listed roles may access this area --> <role-name>friend</role-name> <role-name>guest</role-name> </auth-constraint> </security-constraint> <login-config> <auth-method>DIGEST</auth-method> <realm-name>BookStore Authentication Area</realm-name> </login-config> <!-- Security roles referenced by this web application --> <security-role> <role-name>friend</role-name> </security-role> <security-role> <role-name>guest</role-name> </security-role>
2 conf/tomcat-users.xml文件中包含如下代码
3 创建数据库文件
create database tomcatusers;
use tomcatusers;
create table users(
user_name varchar(15) not null primary key,
user_pass varchar(15) not null
);
create table user_roles(
user_name varchar(15) not null,
role_name varchar(15) not null,
primary key(user_name,role_name)
);
insert into users values("xiaowang","1234");
insert into users values("xiaoming","1234");
insert into user_roles values("xiaowang","friend");
insert into user_roles values("xiaoming","guest");
4 在conf/servers.xml文件中添加Realm节点
<!-- JDBC Realm -->
<Realm className="org.apache.catalina.realm.JDBCRealm"
driverName="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost/tomcatusers"
connectionName="admin" connectionPassword="123456"
userTable="users" userNameCol="user_name" userCredCol="user_pass"
userRoleTable="user_roles" roleNameCol="role_name" />