當柳上原的風吹向天際的時候...

          真正的快樂來源于創造

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            368 Posts :: 1 Stories :: 201 Comments :: 0 Trackbacks
          權限系統是稍成規模的系統中一個必不可少的部分,操作的可否執行,流程的具體走向,業務的具體步驟都會涉及權限的處理。
          具體來說有兩種權限的控制方式:一種是等級權限控制方式,一種是角色權限控制方式。前者可用于范圍控制,適用于用戶權力大小不同的場合;后者可用于單點控制,適用于用戶權力多寡有異的場合?,F實世界中,軍隊中官銜類似于等級權限控制,現代企業中各司其職的權力分配類似于角色控制。范圍控制前面已經提到過了,今天來談談角色權限控制。

          角色權限控制是把單項權限一項項的賦予用戶,如同現實世界中把具體職位一個個的賦予某個員工一樣。在他執行操作前,先看他是否擁有執行此操作的權限,如果有則執行,否則不執行。

          在這里我們還是采用上一講的業務,實現IDocService的實現類DocService,但要把等級權限控制方式修改成角色權限控制方式,原來的處置是用戶權限高于某個值就能執行操作,現在如果一個用戶有“添加”角色,他就可以添加文檔;如果他缺乏“修改”角色,他就不能修改文檔。

          實現用戶角色權限控制并不復雜,下面請看具體思路:
          1.創建兩個領域對象類:用戶類User和角色類Role,他們之間是一對多的關系,他們對應的表用主外鍵關聯起來。使用Hibernate很容易實現這一關系。
          2.使用AOP,實現IDocService接口的實現類DocService的代理,使用UserRoleController作為前置通知,角色權限控制放入其中。
          3. UserRoleController中,查看用戶是否有執行某項操作的權限,沒有則拋出異常NoRoleException,否則執行的DocService中的函數。

          領域對象類的基類BaseDomainObj,User,Role,Doc等都是它的子類。
          package com.heyang.domain;

          /**
           * 領域對象基類
           * 
          @author 何楊
           * 
          @version 1.00
           * 
          @since 2009-1-5 上午10:26:32
           *
           
          */

          public abstract class BaseDomainObj{
              
          // ID
              protected long id;
              
              
          // 名稱
              protected String name;
              
              
          public String toString(){
                  
          return name;
              }


              
          public long getId() {
                  
          return id;
              }


              
          public void setId(long id) {
                  
          this.id = id;
              }
                  

              
          public String getName() {
                  
          return name;
              }


              
          public void setName(String name) {
                  
          this.name = name;
              }

          }

          User類
          package com.heyang.domain;

          import java.util.LinkedHashSet;
          import java.util.Set;

          /**
           * 領域對象用戶類
           * 
          @author 何楊
           * 
          @version 1.00
           * 
          @since 2009-1-5 上午10:23:25
           *
           
          */

          public class User extends BaseDomainObj{
              
          // 用戶所擁有的權限
              private Set<Role> roles=new LinkedHashSet<Role>();
              
              
          public User(){
                  
              }

              
              
          public User(String name){
                  
          this.name=name;
              }

                  
              
          /**
               * 判斷用戶是否擁有角色。若參數角色名在用戶角色集合中能找到則認為用戶有此角色,即名相同則有,否則無
               * 
          @param roleName :角色名
               * 
          @return
               
          */

              
          public boolean hasRole(String roleName){
                  
          for(Role role:roles){
                      
          if(role.getName().equals(roleName)){
                          
          return true;
                      }

                  }

                  
                  
          return false;
              }


              
          public Set<Role> getRoles() {
                  
          return roles;
              }


              
          public void setRoles(Set<Role> roles) {
                  
          this.roles = roles;
              }
              
          }

          User類的Hibernate映射文件,Set部分是關鍵:
          <?xml version="1.0"?>
          <!DOCTYPE hibernate-mapping PUBLIC 
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
          >
          <hibernate-mapping package="org.hibernate.auction">
            
          <class name="com.heyang.domain.User"
              table
          ="AOPRoleSample_User" lazy="false">
              
          <id name="id" column="ID" >
                
          <generator class="native"/>
              
          </id>
              
          <property name="name" column="name" />
              
          <set name="roles" cascade="all" lazy="false">
                
          <key column="userid"/>
                
          <one-to-many class="com.heyang.domain.Role"/>
              
          </set>
            
          </class>
          </hibernate-mapping>

          Role類:
          package com.heyang.domain;

          /**
           * 領域對象角色類
           * 
          @author 何楊
           * 
          @version 1.00
           * 
          @since 2009-1-5 上午10:32:16
           *
           
          */

          public class Role extends BaseDomainObj{
            
          public Role(){
              
            }

            
            
          public Role(String name){
              
          this.name=name;
            }

          }


          Role類的映射文件:
          <?xml version="1.0"?>
          <!DOCTYPE hibernate-mapping PUBLIC 
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
          >
          <hibernate-mapping package="org.hibernate.auction">
            
          <class name="com.heyang.domain.Role"
              table
          ="AOPRoleSample_Role" lazy="false">
              
          <id name="id" column="ID" >
                
          <generator class="native"/>
              
          </id>
              
          <property name="name" column="name" />
            
          </class>
          </hibernate-mapping>

          DocService類,有了AOP的幫忙,其中不需要任何權限控制的代碼,它甚至不知道權限控制子系統的存在
          public class DocService extends BaseService implements IDocService {
            
          /**
             * 按ID取得文檔
             * 
          @param id
             * 
          @return
             
          */

            
          public Doc getDoc(long id){
              
          return (Doc)dao.get(Doc.class,id);
            }

            
            
          public void add(Doc doc, User user) {
              System.out.println(
          "" + doc + "交由dao處理(存入數據庫)");
              dao.create(doc);
            }


            
          public void delete(Doc doc, User user) {
              System.out.println(
          "" + doc + "交由dao處理(從數據庫刪除)");
              dao.delete(doc);
            }


            
          public void update(Doc doc, User user) {
              System.out.println(
          "" + doc + "交由dao處理(修改數據庫中對應的記錄)");
              dao.update(doc);
            }

          }


          UserRoleController類,它作為DocService的前置處理器,在真正的數據庫操作開始前進行權限處理
          package com.heyang.service;

          import java.lang.reflect.Method;

          import org.springframework.aop.MethodBeforeAdvice;

          import com.heyang.domain.User;
          import com.heyang.exception.NoRoleException;

          /**
           * 實現角色子系統---用戶角色控制
           * 
          @author: 何楊(heyang78@gmail.com)
           * @date: 2009-1-2-下午04:19:13
           
          */

          public class UserRoleController implements MethodBeforeAdvice{
              
          private String addDocRoleName;
              
          private String deleteDocRoleName;
              
          private String updateDocRoleName;
                  
              
          /**
               * 在IDocService的實際方法開始前進行前置處理--用戶角色檢查
               
          */

              
          public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
                  
          // 取得方法名
                  String mothodName=arg0.getName();
                  
                  
          // 取得用戶
                  User user=null;        
                  
          if(arg1.length>1){
                      user
          =(User)arg1[1];        
                  }

                  
                  
          // 根據方法名判斷用戶是否擁有所需要的角色,否則拋出異常
                  if("add".equals(mothodName)){
                      
          if(user.hasRole(addDocRoleName)==false){
                          
          throw new NoRoleException("用戶"+user+"必須擁有‘添加’角色才能執行添加文檔操作");
                      }

                  }

                  
          else if("delete".equals(mothodName)){
                      
          if(user.hasRole(deleteDocRoleName)==false){
                          
          throw new NoRoleException("用戶"+user+"必須擁有‘刪除’角色才能執行刪除文檔操作");
                      }

                  }

                  
          else if("update".equals(mothodName)){
                      
          if(user.hasRole(updateDocRoleName)==false){
                          
          throw new NoRoleException("用戶"+user+"必須擁有‘修改’角色才能執行修改文檔操作");
                      }

                  }

              }



              
          public String getAddDocRoleName() {
                  
          return addDocRoleName;
              }



              
          public void setAddDocRoleName(String addDocRoleName) {
                  
          this.addDocRoleName = addDocRoleName;
              }



              
          public String getDeleteDocRoleName() {
                  
          return deleteDocRoleName;
              }



              
          public void setDeleteDocRoleName(String deleteDocRoleName) {
                  
          this.deleteDocRoleName = deleteDocRoleName;
              }



              
          public String getUpdateDocRoleName() {
                  
          return updateDocRoleName;
              }



              
          public void setUpdateDocRoleName(String updateDocRoleName) {
                  
          this.updateDocRoleName = updateDocRoleName;
              }

          }

          全體配置文件
          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
          <beans>
              
          <!-- 數據源 -->
              
          <bean id="dataSource"
                  class
          ="org.springframework.jdbc.datasource.DriverManagerDataSource">
                  
          <property name="driverClassName"
                      value
          ="org.gjt.mm.mysql.Driver">
                  
          </property>
                  
          <property name="url" value="jdbc:mysql://127.0.0.1/test">
                  
          </property>
                  
          <property name="username" value="root"></property>
                  
          <property name="password" value="hy"></property>
              
          </bean>
              
              
          <!-- Hibernate Session Factory,使用了上面配置的數據源 -->
              
          <bean id="sessionFactory"
                  class
          ="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
                  
          <property name="dataSource">
                      
          <ref bean="dataSource"/>
                  
          </property>
                  
          <property name="mappingResources">
                    
          <list>
                      
          <value>com/heyang/domain/User.hbm.xml</value>
                      
          <value>com/heyang/domain/Role.hbm.xml</value>
                      
          <value>com/heyang/domain/Doc.hbm.xml</value>
                    
          </list>
                  
          </property>
                  
          <property name="hibernateProperties">
                      
          <value>
                          hibernate.hbm2ddl.auto=Acreate
                          hibernate.dialect=org.hibernate.dialect.MySQLDialect
                          hibernate.show_sql=true    
                          hibernate.format_sql=true                            
                      
          </value>
                  
          </property>        
              
          </bean>
              
              
          <!-- Hibernate Template,使用了上面配置的sessionFactory -->
              
          <bean id="hibernateTemplate"
                  class
          ="org.springframework.orm.hibernate3.HibernateTemplate">
                  
          <property name="sessionFactory">
                      
          <ref bean="sessionFactory"/>
                  
          </property>
              
          </bean>
              
              
          <!-- 使用了上面配置的hibernateTemplate的BaseDao -->
              
          <bean id="dao" class="com.heyang.dao.BaseDao">
                  
          <property name="hibernateTemplate">
                      
          <ref bean="hibernateTemplate"/>
                  
          </property>
              
          </bean>
              
              
          <!-- 使用了上面配置的dao的UserService -->
              
          <bean id="userService" class="com.heyang.service.UserService">
                  
          <property name="domainClass">
                      
          <value>User</value>
                  
          </property>
                  
          <property name="dao">
                      
          <ref bean="dao"/>
                  
          </property>
              
          </bean>
              
              
          <!-- 用于文件處理的IDocService實現類DocService -->
              
          <bean id="docService" class="com.heyang.service.DocService">
                  
          <property name="dao">
                      
          <ref bean="dao"/>
                  
          </property>
              
          </bean>
              
              
          <!-- 在執行docService的實際方法前進行用戶角色檢查 -->
              
          <bean id="userRoleController" class="com.heyang.service.UserRoleController">
                  
          <property name="addDocRoleName" value="添加" />
                  
          <property name="deleteDocRoleName" value="刪除" />
                  
          <property name="updateDocRoleName" value="修改" />        
              
          </bean>
              
              
          <!-- docService的代理對象 -->
              
          <bean id="docServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
                  
          <property name="proxyInterfaces">
                      
          <value>com.heyang.service.IDocService</value>
                  
          </property>
                  
          <property name="interceptorNames">
                      
          <list>
                          
          <value>userRoleController</value>
                      
          </list>
                  
          </property>
                  
          <property name="target">
                      
          <ref bean="docService"/>
                  
          </property>
              
          </bean>
          </beans>

          模擬處理:
                  ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
                  
                  UserService userService
          =(UserService)ctx.getBean("userService");
                  IDocService docService
          =(IDocService)ctx.getBean("docServiceProxy");
                  
                  User user
          =userService.getUser(1);
                  Doc doc1;
                  
                  
          // 模擬添加操作
                  doc1=new Doc("論次貸危機對美國的影響");
                  
          try{
                      docService.add(doc1, user);
                  }

                  
          catch(NoRoleException ex){
                      ex.printStackTrace();
                  }

                  
                  
          // 模擬修改操作
                  doc1=docService.getDoc(1);
                  doc1.setName(
          "論次貸危機對中國的影響");
                  
          try{
                      docService.update(doc1, user);
                  }

                  
          catch(NoRoleException ex){
                      ex.printStackTrace();
                  }

                  
                  
          // 模擬刪除操作
                  doc1=docService.getDoc(1);
                  doc1.setName(
          "論次貸危機對世界的影響");
                  
          try{
                      docService.delete(doc1, user);
                  }

                  
          catch(NoRoleException ex){
                      ex.printStackTrace();
                  }

          小結:

          權限子系統是企業應用中不可或缺的環節,它具體的權限控制方式有兩種:一種是等級權限控制方式,一種是角色權限控制方式,其他復雜的權限系統都可以由它們組合而來。

          由于業務控制的關系,權限子系統和其他業務子系統的最容易耦合在一起,久而久之會對程序的可讀性,可維護性帶來消極影響,而AOP恰好能幫助我們有效降低權限子系統和其他業務子系統的耦合,實現他們之間的離散化。因此,AOP值得我們認真掌握,尤其是其背后面向方面編程的精神。


          代碼下載:
          http://www.aygfsteel.com/Files/heyang/AOPRoleSample20090106060255.rar

          需要的庫請自行補充(基本ProjectTodolist的lib全有)。
          posted on 2009-01-05 21:38 何楊 閱讀(2038) 評論(2)  編輯  收藏

          Feedback

          # re: 用戶角色權限控制的實現 2009-04-22 20:24 小何
          有沒有角色,用戶控制權限(細粒度)的例子,我最近也在做一個項目的權限控制,但找不到好的例子,有就發給我一下,郵箱是:hgyang_1984@126.com,謝謝~  回復  更多評論
            

          # re: 用戶角色權限控制的實現 2009-04-22 22:44 hy
          http://www.aygfsteel.com/heyang/archive/2009/04/02/263471.html

            回復  更多評論
            


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 精河县| 安多县| 延津县| 永登县| 乌鲁木齐县| 胶州市| 东兰县| 新乐市| 清丰县| 两当县| 交口县| 历史| 通州区| 庆安县| 东至县| 乌兰察布市| 会泽县| 尖扎县| 普定县| 苍梧县| 福清市| 安新县| 军事| 洛川县| 沅陵县| 霍城县| 建始县| 营口市| 牟定县| 双辽市| 勐海县| 洞头县| 工布江达县| 水富县| 汝城县| 大兴区| 满洲里市| 郁南县| 石河子市| 阳曲县| 塘沽区|