role=(Role)roles.get(i);
list.add(newLabelValue(role.getName(),role.getName()));
}
returnlist;
}
}
应用程序启动时,调用StartupListener初始化ServletCOntext环境变量、Spring环境变量和取得角色信息后,接着执行UserCounterListener监听器。
★UserCounterListener功能:
计算使用应用的用户个数和存储用户对象。
应用启动使初始化用户数变量counter,并存入ServletContext,利用HttpSessionAttributeListener监听器每当Session中的属性值有变化时,修改ServletContext中的用户个数和,用户对象。
提供了一种全局跟踪用户信息的方法。
UserCounterListener监听器实现比较简单,主要时理解ServletContextListener和HttpSessionAttributeListener监听器的使用。
★web.xml
org.dudu.webapp.listener.UserCounterListener
★ UserCounterListener监听器程序:
UserCounterListener出来继承了ServletContextListener监听器接口外,还继承了
HttpSessionAttributeListener监听器接口。
ServletContextListener监听器接口的作用已经在“初始化”前一部分作了介绍。
★ HttpSessionAttributeListener监听器介绍:
HttpSessionAttributeListener监听
HttpSession中的属性的操作。
当在Session增加一个属性时,激发
attributeAdded(HttpSessionBindingEventse)方法;当在Session删除一个属性时,激发
attributeRemoved(HttpSessionBindingEventse)方法;当在Session属性被重新设置时,激
发attributeReplaced(HttpSessionBindingEventse)方法。
publicclassUserCounterListenerimplementsServletContextListener,
HttpSessionAttributeListener{
publicstaticfinalStringCOUNT_KEY="userCounter";
publicstaticfinalStringUSERS_KEY="userNames";
privatefinaltransientLoglog=LogFactory.getLog(UserCounterListener.class);
privatetransientServletContextservletContext;
privateintcounter;
privateSetusers;
publicsynchronizedvoidcontextInitialized(ServletContextEventsce){
servletContext=sce.getServletContext();
servletContext.setAttribute((COUNT_KEY),Integer.toString(counter));
}
publicsynchronizedvoidcontextDestroyed(ServletContextEventevent){
servletContext=null;
users=null;
counter=0;
}
synchronizedvoidincrementUserCounter(){
counter=
Integer.parseInt((String)servletContext.getAttribute(COUNT_KEY));
counter++;
servletContext.setAttribute(COUNT_KEY,Integer.toString(counter));
if(log.isDebugEnabled()){
log.debug("UserCount:
"+counter);
}
}
synchronizedvoiddecrementUserCounter(){
intcounter=
Integer.parseInt((String)servletContext.getAttribute(COUNT_KEY));
counter--;
if(counter<0){
counter=0;
}
servletContext.setAttribute(COUNT_KEY,Integer.toString(counter));
if(log.isDebugEnabled()){
log.debug("UserCount:
"+counter);
}
}
synchronizedvoidaddUsername(Objectuser){
users=(Set)servletContext.getAttribute(USERS_KEY);
if(users==null){
users=newHashSet();
}
if(log.isDebugEnabled()){
if(users.contains(user)){
log.debug("Useralreadyloggedin,addinganyway...");
}
}
users.add(user);
servletContext.setAttribute(USERS_KEY,users);
incrementUserCounter();
}
synchronizedvoidremoveUsername(Objectuser){
users=(Set)servletContext.getAttribute(USERS_KEY);
if(users!
=null){
users.remove(user);
}
servletContext.setAttribute(USERS_KEY,users);
decrementUserCounter();
}
publicvoidattributeAdded(HttpSessionBindingEventevent){
if(event.getName().equals(Constants.USER_KEY)){
addUsername(event.getValue());
}
}
publicvoidattributeRemoved(HttpSessionBindingEventevent){
if(event.getName().equals(Constants.USER_KEY)){
removeUsername(event.getValue());
}
}
publicvoidattributeReplaced(HttpSessionBindingEventevent){
//Idon'treallycareiftheuserchangestheirinformation
}
}
图表1管理器类图
(3) 的说明:
LookupDAOHibernate类
图表2实体类图
publicclassLookupDAOHibernateextendsBaseDAOHibernateimplementsLookupDAO{
publicListgetRoles(){
if(log.isDebugEnabled()){
log.debug("retrievingallrolenames...");
}
returngetHibernateTemplate().find("fromRoleorderbyname");
}
}
集成Spring,StartupListener通过管理类LookupManagerImpl,委派LookupDAOHibernate类取得所有角色信息。
然后将角色信息列表存入ServletContext环境上下文中。
StartupListener结束.
第二部分:
权限认证
Appfuse的用户管理,它用到了容器管理的Form认证方式。
1.appfuse应用采用基于表单的登陆验证方式,登陆请求由login.jsp处理。
web.xml
FORM
/login.jsp
/loginError.jsp
2.通过静态应用,login.jsp将登陆请求委派给loginForm.js处理
login.jsp
importurl="/WEB-INF/pages/loginForm.jsp"/>
3.登陆请求由loginservlet截获处理
WEB-INF/pages/loginFrom.jsp
—此处/authorize访问被Servlet拦截-->
urlvalue="/authorize"/>"
onsubmit="saveUsername(this);returnvalidateForm(this)">
web.xml
listenPort_http
8080
<使用SSL安全套接字>
listenPort_https
8443
--LoginServlet截获用户登陆请求-->
login
LoginServlet
org.appfuse.webapp.action.LoginServlet
authURL
j_security_check
isSecure
false
encrypt-password
true
algorithm
SHA
1
login
/authorize/*
4.处理登陆请求的LoginServlet,它出来初始化参数,生成处理过后的URL,然后在交由
LoginFilter处理
publicvoidinit()throwsServletException{
//取得初始化参数
authURL=getInitParameter(Constants.AUTH_URL);
algorithm=getInitParameter(Constants.ENC_ALGORITHM);
secure=Boolean.valueOf(getInitParameter("isSecure"));
encrypt=Boolean.valueOf(getInitParameter("encrypt-password"));
//存储安全认证参数
config.put(Constants.HTTP_PORT,httpPort);
config.put(Constants.HTTPS_PORT,httpsPort);
//classConstants中的定义
//publicstaticfinalStringSECURE_LOGIN="secureLogin";
config.put(Constants.SECURE_LOGIN,secure);
config.put(Constants.ENC_ALGORITHM,algorithm);
config.put(Constants.ENCRYPT_PASSWORD,encrypt);
ctx.setAttribute(Constants.CONFIG,config);
★ 以下为appfuse表单认证设置
Web.xml中的设置
—任何用户都可以访问passwordHintandsignup-->
Unrestricted
Alluserscanview
/passwordHint.html
/signup.html