我们在定义权限时,首先要还是要清楚的了解到权限的分类这一概念问题:
说的简单一点,我们使用拦截器对用户的访问权限进行控制时,总不能全部到拦截到吧,如果全部拦截,我们甚至连登陆都做不到,因此我们要清楚的知道有哪些权限需要我们来进行控制,将这些权限的action地址统一存储到我们的数据库的权限列表中,在进行数据访问时,我们只需要获取到url栏中的地址,查看这个权限是否需要我们控制,如果需要,我们再对这个权限进行控制。
问题1:我们如何定义定义一个拦截器?
首先在struts.xml文件进行配置
先声明拦截器
<interceptor name="checkPrivilege" class="cn.itcast.oa.util.CheckPrivilegeInterceptor"></interceptor>
class 为拦截器启动时对应加载的类
要定义拦截器类首先要继承com.opensymphony.xwork2.interceptor.AbstractInterceptor这个抽象类
实现类中的intercepter方法
package com.nan.util;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class LanJie extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation arg0) throws Exception {
// TODO Auto-generated method stub
return null;
}
}
问题2:我们定义好拦截器如何使用
首先在配置文件struts.xml中定义使用拦截器栈
<interceptor-stack name="defaultStack">
<interceptor-ref name="checkPrivilege"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
在类中定义业务逻辑:注意业务逻辑本身还是要看这个用户有没有这个权限(登陆这种情况要特殊对待应该全部放行否则无论怎么跳都是到登陆页 面)
public String intercept(ActionInvocation invocation) throws Exception {
//获取action地址
String namespace = invocation.getProxy().getNamespace();
String actionName = invocation.getProxy().getActionName();
String privUrl = namespace + actionName;
//从session中获取当前的登陆对象
Employee employee=(Employee)ActionContext.getContext().getSession().get("employee");
//在类中定义拦截逻辑
// 判断登陆对象是否为空
if (employee == null) {
if (privUrl.startsWith("/user_login")) { // "/user_loginUI", "/user_login"
//如果对象本身执行的就是登陆操作 直接放行
return invocation.invoke();
} else {
// 如果是其它的操作 直接跳到登陆页
return "loginUI";
}
}
//如果用户已经登录了
else {
if (employee.hasPrivilegeByUrl(privUrl))
{
// 判断当前地址栏中的action地址是否属于该用户的权限
return invocation.invoke();
} else {
// 没有改权限就跳到没有权限登录的页面
return "noPrivilegeError";
}
}
}
//前面一开始就说了对权限进行区分,就是在 hasPrivilegeByUrl()这个方法中定义
public boolean hasPrivilegeByUrl(String privUrl) {
// 超级管理有所有的权限
if (isAdmin()) {
return true;
}
// >> 去掉后面的参数
int pos = privUrl.indexOf("?");
if (pos > -1) {
privUrl = privUrl.substring(0, pos);
}
// >> 去掉UI后缀
if (privUrl.endsWith("UI")) {
privUrl = privUrl.substring(0, privUrl.length() - 2);
}
// 如果本URL不需要控制,则登录用户就可以使用
Collection<String> allPrivilegeUrls = (Collection<String>) ActionContext.getContext().getApplication().get("allPrivilegeUrls");
if (!allPrivilegeUrls.contains(privUrl)) {
return true;
} else {
// 普通用户要判断是否含有这个权限
for (Role role : roles) {
for (Privilege priv : role.getPrivileges()) {
if (privUrl.equals(priv.getUrl())) {
return true;
}
}
}
return false;
}
}
上面的程序中还有一个问题:.get("allPrivilegeUrls");获得的这个collection对象在哪呢?我们让它在初始化的时候就进行加载
如何实现这个需求呢?首先我们需要知道如何实现初始化加载程序
在web.xml 文件中配置监听 注意需要配置在spring容器之后,因为我们要将对象放在spring容器中
<!-- 配置Spring的用于初始化容器对象的监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext*.xml</param-value>
</context-param>
<!--
用于做初始化工作的监听器,一定要配置到Spring的ContextLoaderListener之后,因为要用到Spring的容器对象
-->
<listener>
<listener-class>cn.itcast.oa.util.InitListener</listener-class>
</listener>
要想使我们定义的InitListener类实现监听的功能,还需要实现 javax.servlet.ServletContextListener;接口, 并实现接口中的方法
package com.nan.util;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class LisennerTest implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
@Override
public void contextInitialized(ServletContextEvent sce) {
}
}
在初始化的方法中定义我们需要进行初始化的内容:
要初始化的内容其实就是将数据库中的内容查询出来,那么问题是我们怎么去调用查询的方法呢?通过spring获取容器对象
public void contextInitialized(ServletContextEvent sce) {
// 获取容器与相关的Service对象
ApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
PrivilegeService privilegeService = (PrivilegeService) ac.getBean("privilegeServiceImpl");
// 准备数据:topPrivilegeList
List<Privilege> topPrivilegeList = privilegeService.findTopList();
sce.getServletContext().setAttribute("topPrivilegeList", topPrivilegeList);
System.out.println("------------> 已准备数据topPrivilegeList <------------");
// 准备数据:allPrivilegeUrls
Collection<String> allPrivilegeUrls = privilegeService.getAllPrivilegeUrls();
sce.getServletContext().setAttribute("allPrivilegeUrls", allPrivilegeUrls);
System.out.println("------------> 已准备数据allPrivilegeUrls <------------");
}