安全性
web应用程序的内容是受限制的,只有授权用户通过用户密码才可以访问。
servlet支持通过配置部署描述器(web.xml)对内容进行访问控制。
servlet容器通过一个叫验证器的阀来支持安全限制。当servlet容器启动的时候,验证阀会添加到Context容器的管道中。在调用wrapper阀之前,会先调用验证器阀,对当前用户进行身份验证,通过才可以继续调用后续的阀。
验证器阀,调用Context容器的领域对象的authenticate()方法,传入用户密码。
servlet安全,包含几个安全对象。领域、主体和角色。
领域
领域对象,用来对用户身份进行验证的组件。一般与一个context容器关联。一个context只有一个领域。通过调用Context容器的setRealm()方法,关联。
领域保存了所有有效用户,的用户名和密码对,或者它会访问相应的存储器。Tomcat中,有效用户信息默认存储在tomcat-user.xml中。
是Realm接口的实例。该接口中有4个用来对用户进行身份验证的重载方法。
主体对象(GenericPrincipal类)
是java.security.Principal接口的实例。它必须与一个领域对象相关联。
public GenericPrincipal(Realm realm,String name,String password){
}
登录配置
是final型的org.apache.catalina.deploy.LoginConfig类的实例。其中包含一个领域对象名字。LoginConfig实例封装领域对象名 和所要使用的身份验证方法
可以调用LoginConfig实例的getRealmName()获取领域名字。 使用getAuthName()方法获取使用的身份验证方法名字。
Tomcat部署中,需要读取web.xml文件内容。如果包含login-config元素,就会创建一个该对象。并设置相应属性,验证器阀会调用LoginConfig对象getRealmName()将返回值传给浏览器。显示在浏览器登录对话框。如果返回null,将服务器以及端口号发送给浏览器。
Authenticator接口
验证器是它的实例。接口本身没有方法,只是标记。 它的实例AuthenticatorBase类,还实现了ValueBase类。也就是说它也是个阀。
验证器的重要工作是对用户进行身份验证。
安装验证器阀
在web.xml中login-config只能出现一次。该元素包含一个auth-method元素来指定身份验证方法。
由于使用的验证器是在运行时才确定的,因此该类是动态载入。
private synchronized void authenticatorConfig(){
//检测关联的context是否有安全限制,没有则返回,不安装验证器
SecurityConstraint constraints[] = context.findConstraints();
if(constraints==null ||constraints.length ==0){
return;
}
//如果当前context容器有一个或者多个安全限制,检测该实例是否有LoginConfig对象
LoginConfig loginConfig = context.getLiginConfig();
if(loginCinfig == null){
loginConfig = new LoginConfig("NONE",null,null,null);
context.setLoginConfig(loginConfig );
}
//检测当前Context对象的管道中的基础阀或附加阀,是否是验证器。因为一个context只能有一个验证器。如果存在直接返回。
Pipeline pipeline = ((StandardContex)context).getPipeline();
if(pipeline !=null){
Value basic = pipeline.getBasic();
if(basic !=null && basic instanceof Authenticator)
return;
for(int i=0;i<values.lenght;i++){
if(values[i] instanceof Authenticator)
return
}
}
//之后检测当前context是否关联领域。如果没有不安装验证器。
if(context.getRealm() ==null){
return;
}
//找到领域对象,则动态载入BasicAuthenticator类,作为阀添加
反射拿到类
context.addValue();
}