srverlet Container或web应用程序本身都可以提供控制web应用程序资源的安全防护
前者称为容器管理的安全防护,或者称为应用程序管理安全防护
通过内嵌机制,tomcat提供一些安全防护方法,这是一种“容器管理”的安全防护。另一方面如果有一系列具有自己的登录机制的servlet和JSP,则视为应用程序管理的安全防护。
不管是哪种安全防护类型,都是用称之为领域(realm)的组来管理用户和密码。
下面将介绍conf/server.conf中领域的配置(定义了如何存储用户与角色信息),以及web应用程序的WEB_INF/web.xml中的<security-constraint>(如何对webapp的用户进行授权)
一、领域的配置
Tomcat含有可插入式的领域架构,且具备多种有用的领域实现:
- UserDatabaseReal
- JDBCRealm
- JNDIRealm
- JAASRealm
- DataSourceRealm
- MemoryRealm
- CombinedRealm
- LockOutRealm
Java开发者可创建额外的领域实现,以便作为与其用户和密码的接口。如欲指定使用何种领域,在server.conf配置文件中插入Realm元素,以className属性设定要使用的领域,然后通过 该实现的自定义属性以提供此领域相关的配置信息:
<Realm className="SOME.REALM.IMPLEMENTATION.CLASSNAME"
CUSTOMATRRIBUTION1="SOME CUSTOM VALUE"
CUSTOMATTRIBUTION2="SOME OTHER CUSTOM VALUE"/>
后面的realm配置可以覆盖前面
每种不同的Realm 采用了不同的用户名和密码存储和使用方式,tomcat默认使用的是UserDatabaseRealm。
1、UserDatabaseRealm
UserDatabaseRealm是从静态文件加载到内存中,且直到tomcat停止后才从内存中清除。事实上,tomcat所用的用户、密码及角色只存在于内存中。换句话说,权限文件只会在启动时,读入一次,在UserDatabaseRealm中分配权限的默认文件为$CATALINA_HOME/conf/tomcat-user.xml(如果更改了tomcat-user.xml文件但没有重启tomcat,则除非重启tomcat,否则tomcat不会重启读入该文件)
tomcat-user.xml文件是使用该领域的关键。它包含一份可访问web应用程序的用户清单。该文件是一个简单的xml文件,根元素是tomcat-users,且只能使用role和user元素。
每个role元素只有一个属性:rolename。
而每个user元素则有3个属性:username、password及roles
role元素:定义rolename,即角色名称,可以定义多个
user元素:定义username用户名、password密码、roles使用上述的哪个角色(多个角色名称之间使用逗号分隔),可以定义多个
UserDatabaseRealm是基于MemoryRealm扩展出来的,默认是读取tomcat-users.xml(可通过Resource中的pathname属性配置为其它文件)里面配置的用户角色信息。
server.xml中的默认配置如下:
不过他是通过应用jndi的方式实现的,从设计上支持多种实现方式,默认采用了类似MemoryRealm的实现方式,但是又对其进行了扩展,主要是增加了“用户组”的概念,即用户除了有所属角色外,还可以有所属“用户组”,用户组可以关联其它多个角色,例如它可以使用下面的tomcat-users.xml配置:
<role rolename="tomcat"/>
<role rolename="admin"/>
<user username="tomcat" password="tomcat" roles="tomcat"/>
<group groupname="one" roles="tomcat"/>
<user username="admin" password="admin" roles="admin" groups="one"/>
admin用户由于关联了“one”这个用户组,“one”用户组包含角色“tomcat”,所以admin用户就拥有了“tomcat”角色。
这个安全域的配置:
1. sever.xml的GlobalNamingResources节点下添加:
<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" />
2.在Engine中启用该安全域的配置:
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
<Realm/>元素可以:
放在<Engine/>元素中,这时该Realm会被所有应用共享。
放在<Host/>元素中,会被该Host下的应用程序共享。
放在<Context/>元素中,则只有对应的应用程序能被访问
2、JDBCRealm
相对于UserDataBaseRealm而言,JDBCRealm具有更大潜在的灵活性,并能动态访问数据,基本上是使用关系型数据库的领域。这个Realm是基于数据库的,数据库中保存了用户名/密码和用户的角色,通过建立数据库的通信来维持用户角色信息
1. 所需要的数据库脚本
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( user_name , user_pass ) values ( 'admin','admin')
insert into users( user_name , user_pass ) values ( 'tomcat','admin')
insert into user_roles(user_name,role_name) values ( 'admin','admin')
insert into user_roles(user_name,role_name) values ( 'tomcat','tomcat')
2.修改tomcat中server.xml添加安全域配置(必须做,设置JDBC的连接参数设成领域的属性,也可以在webapp的context配置文件中配置):
<Realm className="org.apache.catalina.realm.JDBCRealm"
connectionName="sa"
connectionPassword=""
connectionURL="jdbc:h2:tcp://localhost//home/conquer/mine/work_space/h2-dbpath/tomcat"
driverName="org.h2.Driver"
userTable="users" userNameCol="user_name" userCredCol="user_pass"
userRoleTable="user_roles" roleNameCol="role_name"/>
</Realm>
领域属性详解:
className 此Realm实现的java类名,对JDBC而言,必须是org.apache.catalina.realm.JDBCRealm
connectionName 用来建立JDBC连接数据的用户名
connectionPassword 用来建立JDBC连接的数据库密码
connectionURL 用来建立JDBC连接的数据库URL
digest 摘要算法(SHA、MD2或只有MD5),默认值是cleartext
driverName JDBC驱动程序的java类名
roleNameCol 含有角色名(指定给用户)的角色表中的字段名
userNameCol 在用户与角色数据表中,列出用户名的字段名
userCredCol 在用户数据表中,列出用户密码的字段名
userRoleTable 将角色映射至用户的数据表名
userTable 列出用户与密码的数据表名
注意事项:
在配置Tomcat的JDBCRealm的时候,有几个应该注意的地方
1). 数据库JDBC驱动应该放在${tomcat.home}/server/lib目录下,而不能放在webapps的lib目录下,二者的class loader不同
2). tomcat在启动时只会自动装载后缀为.jar的jar包,因此如果使用oracle9i的驱动,应把class12.zip改名为class12.jar
3). 最好将JDBCRealm的配置信息放在webapp的context配置文件中,而不要放在server.xml中
4)<Realm/>元素可以放在<Engine/>元素中,这时该Realm会被所有应用共享。
放在<Host/>元素中,会被该Host下的应用程序共享。
放在<Context/>元素中,则只有对应的应用程序能被访问
3、JNDIRealm
如果让tomcat从LDAP目录中获取用户名称、密码及角色,可使用JNDIRealm。
JNDIRealm是非常有弹性的Realm实现,可以依据用户名、密码及角色的LDAP目录来验证用户的身份,同时还允许该数据用于许多不同的模式布局。
JNDIRealm可递归地搜索LDAP层次目录,直到找到所需要的信息为止,
或者可以设定在目录服务器的特定位置中查找
可以将密码存储为明码形式,并使用基本验证,或存储层摘要编码形式,而使用摘要验证法
其它示例:
领域属性详解:
className 此领域实现的Java类名,对于JNDIRealm,必须是org.apache.catalina.realm.JNDIRealm
connectionName 用来验证只读的LDAP连接的用户名,如果未设定则会建立匿名连接
connectionPassword 用来建立只读的LDAP连接密码
connectionURL 用来建立LDAP连接的目录URL
conetextFactory 用于此连接的JNDI程序厂商的完全限定的java类名,如果未设定则使用默认的JNDI LDAP提供商类
digest 摘要算法(SHA、MD2或MD5),默认值是cleartext
roleBase 查询角色信息的LDAP基本目录条目,如果未指定,默认使用目录范围中的顶层元素
roleName 搜寻包含角色名的领域属性名,此属性可与userRoleName合并使用,若未指定,则只会从用户的目录中取得角色
userRoleName 在用户目录中包含关联用户角色名的属性名,含有此用户角色名称的用户目录中的属性名称。
此属性可与roleName合并使用。如果未设定,则用户的所有角色都来自角色搜索
roleSubtree 如果想要从用户相关的角色的roleBase中以递归方式检索设定的元素的子树,则需要设为true。
如果未设定,则导致默认值false只会搜寻最上层(非递归方式的搜寻)
userPattern 用户目录识别名(DN,distinguished name)的样式,遵从java.text.MessageFormat的语法,用{0}标记插入的实际用户名
userPassword 属性名,用户目录中包含的用户口令。
如果设定此值,则JNDIRealm会用connectionName与connectionPassword属性的指定值绑定至目录,并从目录服务器中获取对应的口令属性,以便与正在被验证的用户指定的属性值比对。如果设定了digest属性,则在比对用户提供的密码与获取自目录服务器的属性值之前,会先对改密码应用摘要算法;如果未设定则JNDIRealm会以用户目录的DN以及用户指定的密码尝试单纯第绑定至目录
userBase 设定以userSearch表达式搜寻用户的基本元素。如果未设定,则会使用目录范围中的顶层元素;如果使用userPattern表达式,则会忽略此属性
userSearch 当搜索用户目录时,所有的LDAP过滤表达式,以{0}标记实际插入用户名的位置,
使用此属性(以及userBase和userSubtree属性)代替userPattern属性,从目录中检索用户目录
userSubtree 如果想递归检索用户目录的userBase属性指定的元素子树,则需要设置该值为true。
默认为false,导致仅检索元素子树的顶层(非递归检索)。如果使用userPattern表达式,则会忽略此属性
4、JAAS Realm
这个是基于java的jaas认证和授权服务而设计的,主要就是用到了jaas的“认证”部分,不涉及“授权”,通过向javax.security.auth.Subject#getPrincipals()里面添加用户和角色来完成用户和角色的认证
注意这里的技巧在于,tomcat要在server.xml的该安全域里配置哪些java类型的Principal表示用户,哪些java类型的Principal表示角色,因为jaas的登录模块在验证成功后只能将用户和角色信息都放入到javax.security.auth.Subject#getPrincipals(),通过事先的类型约定来让tomcat识别用户和角色信息。
JAAS实现了标准的“可插入式验证模块”(PAM)架构,此架构可让应用程序独立于验证实现之外,可不经修改应用程序应用程序本身而只需稍微修改应用程序配置设定,在应用程序中插入全新或更新的验证实现(此时为Tomcat),如依据unix的用户/密码/组 数据库,可使用配置好的JAASRealm,验证用户身份,然后更改配置设定,而不需要更改整个领域实现即可重新设定成依据Kerberos来验证。
除此之外,JAAS还支持堆栈式的验证模块,从而在一个验证堆栈中,两个或三个验证模块可以彼此协同使用。对插入式模块进行堆栈处理,允许实现tomcat尚未实现的自定义验证逻辑
这个安全域的配置如下:
<Realm className="org.apache.catalina.realm.JAASRealm"
appName="Sample"
userClassNames="jaas.SamplePrincipal"
roleClassNames="jaas.SampleRolePrincipal"/>
可以看到,上面的配置中指定了jaas.SamplePrincipal表示用户,而jaas.SampleRolePrincipal表示角色。
可通过confiFile属性来配置jaas需要的认证配置文件,或使用java默认-Djava.security.auth.login.config=xx/jaas.config参数来指定领域属性详解:
className 此领域实现的java类名,对于JAASRealm必须是org.apache.catalina.realm.JAASRealm
appName 传给JAAS LoginContext构造函数(并基于JAAS配置挑选适当的登录方法)的应用程序名称。
默认是Tomcat,不过只要在JAAS .java.login.config文件中更改对应名,即可设定成任何所要的值
userClassNames 代表个别用户的javax.security.Principal类清单,以逗号分隔。对于UnixLoginModule设定值,应当包括UnixPrincipal类类
roleClassNames 代表安全角色的javax.security.Principal类清单,以逗号分隔。对于UnixLoginModule,设定值应该包括UnixNumericGroupPrincipal类
userContextClassLoader 告知JAASRealm,或从前后类加载器中加载类,或从Tomcat自身的类加载器加载类,默认值为true
关于jaas的登录模块的实现,请看:
Java认证和授权服务
JAAS 之 认证http://blog.csdn.net/conquer0715/article/details/78204889
Java认证和授权服务JAAS之授权http://blog.csdn.net/conquer0715/article/details/78205755
注意:如果要使用Java认证和授权服务JAAS之认证中的例子,需要进行如下更改:
1. MyLoginModule 文件:
package jaas; import javax.security.auth.Subject; import javax.security.auth.callback.*; import javax.security.auth.login.FailedLoginException; import javax.security.auth.login.LoginException; import javax.security.auth.spi.LoginModule; import java.security.Principal; import java.util.Map; public class MyLoginModule implements LoginModule { // username and password private String username; private char[] password; // the authentication status private boolean userPwdSucceeded = false; private boolean commitSucceeded = false; // user's Principal private Principal userPrincipal; // initial state private Subject subject; private CallbackHandler callbackHandler; /** * Initialize this <code>LoginModule</code>. */ public void initialize(Subject subject, CallbackHandler callbackHandler, Map<java.lang.String, ?> sharedState, Map<java.lang.String, ?> options) { this.subject = subject; this.callbackHandler = callbackHandler; } /** * Authenticate the user by prompting for a user name and password. */ public boolean login() throws LoginException { // prompt for a user name and password if (callbackHandler == null) throw new LoginException("Error: no CallbackHandler available " + "to garner authentication information from the user"); Callback[] callbacks = new Callback[2]; callbacks[0] = new NameCallback("user name"); callbacks[1] = new PasswordCallback("password", false); // callbacks[2] = new TextOutputCallback(TextOutputCallback.INFORMATION, "hello, just a msg!"); // callbacks[3] = new TextOutputCallback(TextOutputCallback.WARNING, "just warn you!"); try { callbackHandler.handle(callbacks); NameCallback nameCallback = (NameCallback) callbacks[0]; PasswordCallback passwordCallback = (PasswordCallback) callbacks[1]; username = nameCallback.getName(); char[] tmpPassword = passwordCallback.getPassword(); passwordCallback.clearPassword();// clean password in memory space if (tmpPassword == null) { tmpPassword = new char[0];// treat a NULL password as an empty password } password = new char[tmpPassword.length]; System.arraycopy(tmpPassword, 0, password, 0, tmpPassword.length); } catch (Exception e) { e.printStackTrace(); } // verify the username/password // boolean usernameCorrect = false; // if (username.equals("user")) usernameCorrect = true; // // if (usernameCorrect && // password.length == 3 && // password[0] == 'p' && // password[1] == 'w' && // password[2] == 'd') { // // userPwdSucceeded = true; // } else { // userPwdSucceeded = false; // cleanUserAndPwdData(); // if (!usernameCorrect) { // throw new FailedLoginException("User Name Incorrect"); // } else { // throw new FailedLoginException("Password Incorrect"); // } // } // return userPwdSucceeded; userPwdSucceeded=true; return true; } public boolean commit() throws LoginException { if (!userPwdSucceeded) return false; // add a Principal (authenticated identity) to the Subject userPrincipal = new SamplePrincipal(username); subject.getPrincipals().add(userPrincipal); // for tomcat jaas realm if (username.equals("admin")) { subject.getPrincipals().add(new SampleRolePrincipal("admin")); } else if (username.equals("tomcat")) { subject.getPrincipals().add(new SampleRolePrincipal("tomcat")); } // in any case, clean out state cleanUserAndPwdData(); return commitSucceeded = true; } public boolean abort() throws LoginException { if (!userPwdSucceeded) return false; if (commitSucceeded) { logout(); } else { cleanState(); } return true; } public boolean logout() throws LoginException { subject.getPrincipals().remove(userPrincipal); cleanState(); userPwdSucceeded = commitSucceeded; return true; } private void cleanState() { userPwdSucceeded = false; cleanUserAndPwdData(); userPrincipal = null; } private void cleanUserAndPwdData() { username = null; if (password != null) { for (int i = 0; i < password.length; i++) password[i] = ' '; password = null; } } }
SamplePrincipal 文件:
package jaas; import java.security.Principal; public class SamplePrincipal implements Principal { private String name; public SamplePrincipal(String name) { this.name = name; } public String getName() { return name; } }
SampleRolePrincipal文件:
package jaas; public class SampleRolePrincipal extends SamplePrincipal { public SampleRolePrincipal(String name) { super(name); } }
说明:
另外注意
userClassNames="jaas.SamplePrincipal" 和 roleClassNames="jaas.SampleRolePrincipal"
两个实现类的 equals 和 hascode 方法,如果覆盖不好最好不要覆盖,否则容易
subject.getPrincipals().add 不进去。
5、DataSourceRealm
这个安全域和上面的JDBCRealm实现基本一致,只不过不是创建数据库连接,而是从JNDI上下文获取数据源,它所需要的数据库脚本和JDBCRealm一致。
修改tomcat的server.xml 添加安全域配置:
1. 在 GlobalNamingResources
节点下添加:
<Resource
name="jdbc/h2"
type="javax.sql.DataSource"
username="sa"
password=""
driverClassName="org.h2.Driver"
url="jdbc:h2:tcp://localhost//home/conquer/mine/work_space/h2-dbpath/tomcat"/>
2. 继续添加安全域配置(这里会使用jndi引用上面注册的数据源资源):
<Realm className="org.apache.catalina.realm.DataSourceRealm"
dataSourceName="jdbc/h2"
userTable="users" userNameCol="user_name" userCredCol="user_pass"
userRoleTable="user_roles" roleNameCol="role_name"/>
</Realm>
6、MemoryRealm
这个是最简单的配置,默认是读取tomcat-users.xml(可通过pathname属性配置为其它文件)里面配置的用户角色信息。
修改server.xml 添加配置:
<Realm className="org.apache.catalina.realm.MemoryRealm"/>
7、CombinedRealm
这是一个特殊的Realm,顾名思义,它可以使用多个子的Realm(Realm可以嵌套)来对用户进行授权。也许你有多个“数据源”,也许你希望当有一个Realm停止工作的时候系统仍然不会崩溃,不管是什么需求需要同时使用多个Realm,这个CombinedRealm就能满足这个需求。授权将会按照子Realm的声明顺序依次进行,只要满足任何一个子Realm,都可以通过校验。
resourceName="UserDatabase"/>
dataSourceName="jdbc/authority"
userTable="users"
userNameCol="user_name"
userCredCol="user_pass"
userRoleTable="user_roles"
roleNameCol="role_name"/>
8、LockOutRealm
它继承于CombinedRealm,和CombinedRealm一样,与它一起工作的Realm需要嵌套在LockOutRealm中,而且也是只需要满足任何一个Realm即可。如果在一定的时间内多次尝试授权失败,它将会锁定这个用户。使用它时,不需要修改它下面的Realm配置,因为它是通过记录所有失败的登录(包括不存在的用户)来实现的。
二、web.xml的配置
web.xml安全配置
Servlet规范支持安全地访问web资源,只需要通过web.xml简单配置即可,其功能由服务器提供商实现,
web.xml文件内容如下:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <--!配置 <security-constraint/> 元素,指定角色可访问的资源集和可使用的 HTTP 方法--> <security-constraint> <web-resource-collection> #定义资源集 <web-resource-name>some name</web-resource-name> #指定资源名称 <url-pattern>*.jsp</url-pattern> #匹配资源 <url-pattern>*.do</url-pattern> <http-method>GET</http-method> #可使用的HTTP方法 <http-method>PUT</http-method> <http-method>HEAD</http-method> <http-method>TRACE</http-method> <http-method>POST</http-method> <http-method>DELETE</http-method> <http-method>OPTIONS</http-method> </web-resource-collection> <auth-constraint> #定义认证用户 <role-name>tomcat</role-name> <role-name>admin</role-name> </auth-constraint> tomcat或admin两个角色都可以使用GET|PUT|HEAD|TRACE|POST|DELETE|OPTIONS方法访问*.jsp *.do资源 <user-data-constraint> <transport-guarantee>NONE</transport-guarantee> <!-- 这个可选的元素指出在访问相关资源时使用哪种传输层保护。 它必须包含一个transport-guarantee子元素(合法值为NONE | INTEGRAL | CONFIDENTIAL), transport-guarantee为NONE值将对所用的通讯协议不加限制。 INTEGRAL值表示数据必须以一种防止截取它的人阅读它的方式传送。 虽然原理上(并且在未来的HTTP版本中),在INTEGRAL和CONFIDENTIAL之间可能会有差别,但在当前实践中,他们都只是简单地要求用SSL。 --> </user-data-constraint> </security-constraint> #对一个完整资源的安全的定义结束 <security-constraint> #对另一个资源安全的定义开始 <web-resource-collection> #定义资源集 <web-resource-name>admin page</web-resource-name> #定义资源名称 <url-pattern>/admin.jsp</url-pattern> #资源匹配 </web-resource-collection> <auth-constraint> #定义认证用户 <role-name>admin</role-name> </auth-constraint> </security-constraint> #该资源集安全定义结束,admin.jsp资源只能由admin角色访问
<security-constraint> #第三个资源安全定义开始 <web-resource-collection> #定义资源集 <web-resource-name>tomcat page</web-resource-name> #定义资源名称 <url-pattern>/tomcat.jsp</url-pattern> #匹配资源 </web-resource-collection> <auth-constraint> #定义认证用户 <role-name>tomcat</role-name> </auth-constraint> </security-constraint> #该资源安全定义结束 ,tomcat.jsp资源只能由tomcat角色访问
配置 <login-config/>元素,指定认证方式,并指定安全域 <login-config> <!--<auth-method>BASIC</auth-method>--> <auth-method>FORM</auth-method> 目前认证方式有4种:BASIC(基础认证)|DIGEST(摘要认证)|FROM(表单认证)|CLIENT-CERT(证书认证)
1、BASIC(基础认证):需要提供base64编码文本的用户口令,这种验证方法,所有的密码都会以base64编码文本在网络上传递
示例如下:
2、DIGEST(摘要认证):需要提供摘要编码字符串的用户口令,若使用摘要认证,除了在此web.xml文件中设置外,还需要在server.xml文件中修改Realm设定,将digest属性添加到Realm元素中
并给与该属性MD5值,digest属性值可使用SHA/MD2/MD5,推荐仅使用MD5,在tomcat的密码库(codebase)中对该选项的支持更好
除了告诉tomcat存储密码的方式(MD5)外,还需要以指定格式手动加密每个用户密码,对于每个用户均需执行如下两个步骤:
步骤1:
$CATALINA_HOME/bin/digest.sh -a MD5 123456 #123456是明文密码,执行后返回加密密码
步骤2:将上述冒号后的加密后的密码复制添加到tomcat-user.xml文件中作为某个用户的密码
示例如下:
3、FROM(表单认证):在网页的表单上要求提供用户密码
当用户请求web应用程序受保护的资源时,表单验证会显示登录表单的网页画面,在web应用程序中,为实现表单验证,需要登录表单的网页与验证失败的错误信息网页
示例:
/login.html,form-login-page元素表示当tomcat发现未登录的用户企图访问受到security-constraint保护保护的资源时,需要显示给用户的网页
/error.html,form-error-page元素表示当用户登录失败时,tomcat要显示给用户的网页
4、CLIENT-CERT(证书认证):以客户端数字证书来确认用户的身份
只有当在SSL(即HTTPS)上提供网页内容时,才能使用CLIENT_CERT的验证方(在web.xml文件的auth-method元素中的CLIENT_CERT),它允许客户端认证不用口令,而是浏览器提供客户端X.509数值认证证书作为登录认证
<!-- 使用的Realm名字,注意这里不能有空格 --> <realm-name>MyConstraints</realm-name>
<form-login-config> #只有表单验证(FROM),才需要这里的登录表单网页和验证失败错误信息网页 相对于Web应用程序的根目录的2个文件
<form-login-page>/login.html</form-login-page> #该元素表示当tomcat发现未登录的用户企图访问受到security-constraint保护保护的资源时,需要显示给用户的网页
<form-error-page>/error.html</form-error-page> #用户登录失败时,form-error-page元素展示了tomcat要显示给用户的网页
</form-login-config>
</login-config> 配置<security-role/>元素来定义角色(角色是在tomcat-user.xml文件中事先定义好的)
<security-role>
<role-name>tomcat</role-name>
</security-role>
<security-role>
<role-name>admin</role-name>
</security-role> </web-app>
上述的web.xml文件内容表示:
1、安全规则
admin.jsp 只能由 admin 角色访问,
tomcat.jsp 只能由 tomcat 角色访问,
其它任意 *.jsp *.do 可由 admin 或 tomcat 角色访问。
2、认证方式
BASIC 是基础认证方式,由浏览器厂商实现的用户名和密码接收界面;
FORM 是应用定制的用户名和密码接收页面;
3、角色声明
必需明出所有用到的角色