一、权限控制系统

权限控制系统即用户登录后,如果操作了不能访问的操作,系统将其拦截。
权限控制系统设计需求:

  • 系统功能并不是所有功能都需要被控制,例如登录功能无需校验
    设计方案:资源中没有出现的功能将不被过滤
  • 系统功能中具有访问控制权限的一定出现在资源定义数据中。
  • 用户每次访问某个功能时,必须先进行校验,使用拦截器或AOP完成此功能。

1.自定义权限校验拦截器AuthInterceptor

public class AuthInterceptor extends AbstractInterceptor
复制代码

2.获取当前被拦截的操作信息

String actionName = invocation.getProxy().getAction().getClass().getName();
String methodName = invocation.getProxy().getMethod();
String allName = actionName + "." + methodName;
复制代码
复制代码

3.启动服务器,测试是否拦截到操作信息

4.获取所有的资源信息
首先注入ResourceEbi,使用struts2的自动装配模式

private ResEbi resEbi;//struts会自动的装配
public void setResEbi(ResEbi resEbi) {
this.resEbi = resEbi;
    }
复制代码

获取所有资源信息

检测调用资源是否存在于全资源列表中

//由直接在拦截器里面进行资源查询的时候,每次都需要查询,这样会使得程序的效率很低,
//因此在这里使用监听器,在程序加载的时候就加载好,这样后面就不会再进行查询
String allRes = ServletActionContext.getServletContext().getAttribute("allRes").toString();
if(!allRes.contains(allName)){
return invocation.invoke();
}
复制代码

5.根据用户登陆数据,获取登录人所具有的资源数据,其中关联关系靠角色维护,即员工->角色->资源
获取登陆用户的所有资源
注:session中的登陆用户数据中如果未对关联数据进行初始化无法直接获取

//在登录成功的时候,查询该用户的所有权限
List<ResModel> resList = resEbi.getResByEm(loginEm.getUuid());
StringBuilder sbf = new StringBuilder();
for (ResModel rm : resList) {
    sbf.append(rm.getText());
    sbf.append(",");
}
复制代码

全部代码

public class AuthInterceptor extends AbstractInterceptor{
private ResEbi resEbi;//struts会自动的装配
public void setResEbi(ResEbi resEbi) {
this.resEbi = resEbi;
    }
public String intercept(ActionInvocation invocation) throws Exception {
        String actionName = invocation.getProxy().getAction().getClass().getName();
        String methodName = invocation.getProxy().getMethod();
        String allName = actionName + "." + methodName;
        System.out.println(allName);
//由直接在拦截器里面进行资源查询的时候,每次都需要查询,这样会使得程序的效率很低,
//因此在这里使用监听器,在程序加载的时候就加载好,这样后面就不会再进行查询
        String allRes = ServletActionContext.getServletContext().getAttribute("allRes").toString();
if(!allRes.contains(allName)){
return invocation.invoke();
        }
        EmpModel em = (EmpModel) ActionContext.getContext().getSession().get(EmpModel.EMP_LOGIN_USER_OBJECT_NAME);
//        System.out.println("-----==-----");
//        System.out.println(em.getResAll());
//        System.out.println("-----==-----");
//在登录的时候将用户的权限查询出来提高程序的效率
if(em.getResAll().contains(allName)){
return invocation.invoke();
        }
throw new AppException("对不起你没有访问权限!");
    }
}
复制代码

二、全资源获取优化

系统中每个用户的每个操作均需要依赖拦截器进行校验,其中的功能如果性能过低将使整体系统性能下降。对其中的数据获取进行优化。
由于权限校验时,每次需要判定调用资源是否存在于所有资源列表中,以此判定当前操作是否需要权限拦截,所以需要将该数据的获取进行优化。
将此类数据的共享范围扩大至应用程序范围,将该数据获取后,放置在ServletContext范围内。
1.开发Web监听器

public class AllResLoadListener implements ServletContextListener
复制代码

2.监听器初始化时,获取全资源信息,并将其加载到ServletContext范围内。为后期判定方便,将数据初始化为字符串信息,方便查询,减少集合迭代次数。

public void contextInitialized(ServletContextEvent event) {
        ServletContext sc = event.getServletContext();
        WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sc);
        ResEbi resEbi = (ResEbi) ctx.getBean("resEbi");
        List<ResModel> resList = resEbi.getAll();
        StringBuilder sbf = new StringBuilder();
for(ResModel temp :resList){
            sbf.append(temp.getText());
            sbf.append(",");
        }
//放入sc中
        sc.setAttribute("allRes", sbf.toString());
    }
复制代码

3.配置Web监听器

4.在权限拦截器中获取资源,断开原始获取资源方式

String allRes = ServletActionContext.getServletContext().getAttribute("allRes").toString();
if(!allRes.contains(allName)){
return invocation.invoke();
}
复制代码

全部代码

public class AllResLoadListener implements ServletContextListener{
public void contextInitialized(ServletContextEvent event) {
        ServletContext sc = event.getServletContext();
        WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sc);
        ResEbi resEbi = (ResEbi) ctx.getBean("resEbi");
        List<ResModel> resList = resEbi.getAll();
        StringBuilder sbf = new StringBuilder();
for(ResModel temp :resList){
            sbf.append(temp.getText());
            sbf.append(",");
        }
//放入sc中
        sc.setAttribute("allRes", sbf.toString());
    }
public void contextDestroyed(ServletContextEvent event) {
    }
}
复制代码

三、总结

这里主要是通过java监听器来实现权限的控制和对资源的启动的优化。