java 权限设计 java权限管理系统_d3

此权限管理系统把待访问的业务层方法做为权限管理中的资源,通过spring aop 对接口方法进行拦截,来实现权限的管理,可以实现细粒度的权限控制。

在上文体验了spring aop 一些特性,aop 接口:MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice 实现这三个接口分别对方法执行前,后,执行中抛异常等情况进行的,我们要是想做overload 这样的操作时,要用MethodInterceptor接口,此接口好在有返回值,

java 权限设计 java权限管理系统_调用方法_02

publicObject invoke(
      MethodInvocation invocation) 
      throws Throwable
{
//
.
}

上文做法有些牵强业务逻辑还有throws PermissionDeniedException 感觉不爽,现在用MethodInterceptor 接口,来写这个demo,把权限与业务分开。

advice 如下:

java 权限设计 java权限管理系统_调用方法_03

java 权限设计 java权限管理系统_java 权限设计_04

publicclassPermissionCheckAroundAdvice implements MethodInterceptor
{
    SecurityManager securityMgr=newSecurityManager();
    
/**//**
     * @param securityMgr The securityMgr to set.
*/
publicvoidsetSecurityMgr(SecurityManager securityMgr)
{
this.securityMgr=securityMgr;
    }
publicObject invoke(MethodInvocation invocation) throws Throwable
{
        System.out.println("(被调用方法接口类名:"
+invocation.getMethod().getDeclaringClass().getName()+")");
        System.out.println("(被调用方法名:"+invocation.getMethod().getName()+")");
        String methodName=invocation.getMethod().getDeclaringClass()
                .getName()+"."+invocation.getMethod().getName();
        System.out.println("(被调用方法全名:"+methodName+")");
        System.out.println("有否权限:("+securityMgr.checkPermission(methodName)+")");
if(securityMgr.checkPermission(methodName))
returninvocation.proceed();
         System.out.println("Goodbye! NO Permission!(by"+this.getClass().getName()+")");
return"--";
    }
}

服务层业务接口修改如下:

java 权限设计 java权限管理系统_调用方法_03

java 权限设计 java权限管理系统_java 权限设计_04

publicinterfaceService
{
publicString getBeanInfo();
}

服务层业务实现类如下:

java 权限设计 java权限管理系统_调用方法_03

java 权限设计 java权限管理系统_java 权限设计_04

publicclassServiceBean implements Service
{
    ResourceBean bean;
/**//**
     * @param bean The bean to set.
*/
publicvoidsetBean(ResourceBean bean)
{
this.bean=bean;
    }
publicString getBeanInfo()
{
        String result="";
        
        result+=bean.getMethod1();
        result+=bean.getMethod2();
        result+=bean.getMethod3();
returnresult;
    }
}

资源层,接口 ,类如下:

java 权限设计 java权限管理系统_调用方法_03

java 权限设计 java权限管理系统_java 权限设计_04

publicinterfaceResource
{
}
publicinterfaceResourceBean extends Resource
{
publicvoidtheMethod();
publicString getMethod1();
publicString getMethod2();
publicString getMethod3();
}
publicclassResourceBeanImpl implements ResourceBean,InitializingBean
{
publicvoidtheMethod()
{
        System.out.println(this.getClass().getName()
+"."+newException().getStackTrace()[0].getMethodName()
+"()"
+"says HELLO!");
    }
publicString getMethod1()
{
return"张三";
    }
publicString getMethod2()
{
return"李四";
    }
publicString getMethod3()
{
return"王五";
    }
publicvoidafterPropertiesSet() throws Exception
{
        System.out.println("事件监听:类ResourceBeanImpl属性设置完毕");
        
    }
}

权限管理类:

java 权限设计 java权限管理系统_调用方法_03

java 权限设计 java权限管理系统_java 权限设计_04

publicclassUser
{
    List privilages=newjava.util.ArrayList();
    String name;
publicUser()
{
    }
    
/**//**
     * @param privilages The privilages to set.
*/
publicvoidsetPrivilages(List privilages)
{
this.privilages=privilages;
    }
publicString getName()
{
returnname;
    }
publicvoidsetName(String name)
{
this.name=name;
    }
publicboolean isPermission(String pri)
{
        java.util.Iterator it=privilages.iterator();
        String p="";
        boolean pass=false;
while(it.hasNext())
{
            
            p=(String)it.next();
            System.out.println(p);
if(p.equals(pri))
{
                pass=true;
break;
            }
        }
returnpass;
    }
}
publicclassSecurityManager
{
    User user;
publicvoidsetUser(User user)
{
this.user=user;
    }
publicboolean checkPermission(String privilege)
{
returncheckPermission(user,privilege);
    }
publicboolean checkPermission(User user, String privilege)
{
returnuser.isPermission(privilege);
    }
}

配置文件:

java 权限设计 java权限管理系统_调用方法_02

<?xml  versinotallow="1.0" encoding="UTF-8"?>
beans PUBLIC  "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
com.jhalo.jsecurity.aop.ResourceBean
permissionAroundAdvisor
com.jhalo.jsecurity.aop.Service
permissionAroundAdvisor
tester
com.jhalo.jsecurity.aop.ResourceBean.getMethod3
com.jhalo.jsecurity.aop.Service.getBeanInfo
com.jhalo.jsecurity.aop.ResourceBean.getMethod1
  
  
  
.*

java 权限设计 java权限管理系统_调用方法_02

java 权限设计 java权限管理系统_java 权限设计_15

java 权限设计 java权限管理系统_调用方法_02

java 权限设计 java权限管理系统_调用方法_02

java 权限设计 java权限管理系统_调用方法_02

java 权限设计 java权限管理系统_调用方法_02

User 所拥有的权限是在spring 配置文件中手工配置的,在实际应用中不可行,可以从DB中取得。

测试类:

java 权限设计 java权限管理系统_调用方法_03

java 权限设计 java权限管理系统_java 权限设计_04

publicclassSpringAopTest
{
publicstaticvoidmain(String[] args)
{
//Read the configuration file
ApplicationContext ctx
=newFileSystemXmlApplicationContext("springconfig.xml");
String name="";
Service sb=(Service)ctx.getBean("service");
//System.out.println("---"+ctx.isSingleton("service")+"---");
name=sb.getBeanInfo();
        System.out.println("test result::"+name);
      }
}

测试结果 :

java 权限设计 java权限管理系统_调用方法_02

(xml.XmlBeanDefinitionReader119) Loading XML bean definitions from file [D:\projects\actives\jsecurity\springconfig.xml]
(support.FileSystemXmlApplicationContext90) Bean factoryforapplication context [org.springframework.context.support.FileSystemXmlApplicationContext;hashCode=25853693]: org.springframework.beans.factory.support.DefaultListableBeanFactory defining beans [bean,service,resourceMgr,beanTarget,beanTarget2,user,securityMgr,serviceBean,permissionAroundAdvisor,thePermissionCheckBeforeAdvice,thePermissionThrowsAdvice,thePermissionAroundAdvice]; root of BeanFactory hierarchy
(support.FileSystemXmlApplicationContext287)12beans definedinapplication context [org.springframework.context.support.FileSystemXmlApplicationContext;hashCode=25853693]
(support.FileSystemXmlApplicationContext395) Unable to locate MessageSource with name'messageSource':usingdefault[org.springframework.context.support.StaticMessageSource:
{}]
(support.FileSystemXmlApplicationContext417) Unable to locate ApplicationEventMulticaster with name'applicationEventMulticaster':usingdefault[org.springframework.context.event.SimpleApplicationEventMulticaster@5e5a50]
(support.FileSystemXmlApplicationContext439) Refreshing listeners
(support.DefaultListableBeanFactory236) Creating shared instance of singleton bean'resourceMgr'
(support.FileSystemXmlApplicationContext448) Application listener [com.jhalo.jsecurity.aop.ResourceManager@a3d4cf] added
(support.DefaultListableBeanFactory221) Pre-instantiating singletonsinfactory [org.springframework.beans.factory.support.DefaultListableBeanFactory defining beans [bean,service,resourceMgr,beanTarget,beanTarget2,user,securityMgr,serviceBean,permissionAroundAdvisor,thePermissionCheckBeforeAdvice,thePermissionThrowsAdvice,thePermissionAroundAdvice]; root of BeanFactory hierarchy]
(support.DefaultListableBeanFactory236) Creating shared instance of singleton bean'bean'
(core.CollectionFactory55) Using JDK1.4collections
(support.DefaultListableBeanFactory236) Creating shared instance of singleton bean'beanTarget'

java 权限设计 java权限管理系统_调用方法_02

事件监听:类ResourceBeanImpl属性设置完毕

java 权限设计 java权限管理系统_调用方法_02

(support.DefaultListableBeanFactory236) Creating shared instance of singleton bean'permissionAroundAdvisor'
(support.DefaultListableBeanFactory236) Creating shared instance of singleton bean'thePermissionAroundAdvice'
(support.DefaultListableBeanFactory236) Creating shared instance of singleton bean'securityMgr'
(support.DefaultListableBeanFactory236) Creating shared instance of singleton bean'user'
(support.DefaultListableBeanFactory236) Creating shared instance of singleton bean'service'
(support.DefaultListableBeanFactory236) Creating shared instance of singleton bean'serviceBean'
(support.DefaultListableBeanFactory236) Creating shared instance of singleton bean'beanTarget2'

java 权限设计 java权限管理系统_调用方法_02

事件监听:类ResourceBean2Impl属性设置完毕

java 权限设计 java权限管理系统_调用方法_02

(support.DefaultListableBeanFactory236) Creating shared instance of singleton bean'thePermissionCheckBeforeAdvice'
(support.DefaultListableBeanFactory236) Creating shared instance of singleton bean'thePermissionThrowsAdvice'
--------ContextRefreshedEvent called
(被调用方法接口类名: com.jhalo.jsecurity.aop.Service)
(被调用方法名:getBeanInfo)
(被调用方法全名:com.jhalo.jsecurity.aop.Service.getBeanInfo)
com.jhalo.jsecurity.aop.ResourceBean.getMethod3
com.jhalo.jsecurity.aop.Service.getBeanInfo
有否权限:(true)
com.jhalo.jsecurity.aop.ResourceBean.getMethod3
com.jhalo.jsecurity.aop.Service.getBeanInfo
(被调用方法接口类名: com.jhalo.jsecurity.aop.ResourceBean)
(被调用方法名:getMethod1)
(被调用方法全名:com.jhalo.jsecurity.aop.ResourceBean.getMethod1)
com.jhalo.jsecurity.aop.ResourceBean.getMethod3
com.jhalo.jsecurity.aop.Service.getBeanInfo
com.jhalo.jsecurity.aop.ResourceBean.getMethod1
有否权限:(true)
com.jhalo.jsecurity.aop.ResourceBean.getMethod3
com.jhalo.jsecurity.aop.Service.getBeanInfo
com.jhalo.jsecurity.aop.ResourceBean.getMethod1
(被调用方法接口类名: com.jhalo.jsecurity.aop.ResourceBean)
(被调用方法名:getMethod2)
(被调用方法全名:com.jhalo.jsecurity.aop.ResourceBean.getMethod2)
com.jhalo.jsecurity.aop.ResourceBean.getMethod3
com.jhalo.jsecurity.aop.Service.getBeanInfo
com.jhalo.jsecurity.aop.ResourceBean.getMethod1
有否权限:(false)
com.jhalo.jsecurity.aop.ResourceBean.getMethod3
com.jhalo.jsecurity.aop.Service.getBeanInfo
com.jhalo.jsecurity.aop.ResourceBean.getMethod1
Goodbye!NO Permission!(by com.jhalo.jsecurity.aop.PermissionCheckAroundAdvice)
(被调用方法接口类名: com.jhalo.jsecurity.aop.ResourceBean)
(被调用方法名:getMethod3)
(被调用方法全名:com.jhalo.jsecurity.aop.ResourceBean.getMethod3)
com.jhalo.jsecurity.aop.ResourceBean.getMethod3
有否权限:(true)
com.jhalo.jsecurity.aop.ResourceBean.getMethod3
test result::张三--王五

java 权限设计 java权限管理系统_调用方法_02

这样就完全把企业业务逻辑与权限管理系统分开了,服务层,资源层与权限检查分离,用spring aop 通过配置文件把它们粘合在一起。实现了细粒度(对资源层数据)的权限检查。

接下来在此权限管理系统中引用角色概念,向 rbac 系统进军.(未完待续)

参考资料:

An Introduction to Aspect-Oriented Programming with the Spring Framework, Part 1 by Russell Miles -- The Spring framework, which supports development of the different facets of J2EE, provides an aspect-oriented programming module that gives Spring developers the opportunity to apply aspects to their applications. This article shows you how to work with AOP in Spring.

An Introduction to Aspect-Oriented Programming with the Spring Framework, Part 2 by Russell Miles -- Russ Miles continues his introduction to Aspect-Oriented Programming (AOP) in Spring by delving into the around advice, which allows you to not just add to an existing method implementation, but to completely replace it.

方向:分布式系统设计

posted on 2005-04-08 15:15