<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 0,  comments - 17,  trackbacks - 0
    來源:http://www.tkk7.com/baputista
    還以我傳統(tǒng)的例子為例:
    畢業(yè)設(shè)計選題系統(tǒng),三種角色:教師,學(xué)生,管理員,我想讓他們的登陸都在一個界面下自動識別,而無需進(jìn)行身份選擇,登陸后,他們將分別到各自的admin.jsp,stu.jsp,teacher.jsp
    在數(shù)據(jù)庫中的表結(jié)構(gòu)如下(很多屬性略):
    id--- user---password--type---about

    type是用來存儲用戶的類別,分別有a,t,s分別對應(yīng)三種角色
    about對應(yīng)的是acegi里所需要的enable,用戶是否可用

    在model里,我們采用了繼承關(guān)系:

    父類user:
    package subject.model;

    public abstract class User extends BaseObject
    {
     private Integer id;
     private String user;
     private String password;
     private String name;
     private String telphone;

    //set and get method 
     
     public abstract String getType(); //這個是用來反映用戶角色的關(guān)鍵函數(shù),在子類實現(xiàn),從而實現(xiàn)多態(tài)
    }

    子類的實現(xiàn):
    ======================
    package subject.model;

    import subject.Constants;

    public class Teacher extends User
    {
     private String level;         //教師的職稱

    //set and get method

     public String getType()
     {
      return Constants.TEACHER;
     }
    }
    ================
    package subject.model;

    import subject.Constants;

    public class Student extends User
    {
     private static final long serialVersionUID = 1L;

     private SchoolClass schoolClass;         //學(xué)生的班級
     private String sn;             //學(xué)生的學(xué)號

    //set and get method
     
     public String getType()
     {
      return Constants.STUDENT;
     }
    }
    =================
    package subject.model;

    import subject.Constants;

    public class Admin extends User
    {
     private String grade;           //管理員的級別
    //set and get method

     public String getType()
     {
      return Constants.ADMIN;
     }
    }

    對于三者所共有的屬性在數(shù)據(jù)庫里,都存在一個字段,而依據(jù)不同的角色擁有不同的含義,學(xué)生的班級則存放在了about里,只要學(xué)生有班級,他就able,否則就enable了!而管理員和教師則默認(rèn)為1!

    這種是屬于一個繼承樹存放在一個表的情況,Hibernate的配置如下:
    <hibernate-mapping>

     <class name="subject.model.User" discriminator-value="not null">

      <id name="id">
       <generator class="increment" />
      </id>
      
      <discriminator column="type" type="character" />
      
      <property name="user" />
      <property name="password" />
      <property name="name" />
      <property name="telphone" />

      <subclass name="subject.model.Admin" discriminator-value="a">
       <property name="grade" column="sn" />
      </subclass>
      
      <subclass name="subject.model.Teacher" discriminator-value="t">
       <property name="level" column="sn" />
      </subclass>
      
      <subclass name="subject.model.Student" discriminator-value="s">
       
       <property name="sn" />
       
       <many-to-one name="schoolClass" class="subject.model.SchoolClass"
        column="about" update="false" insert="false" />
        
      </subclass>

     </class>

    </hibernate-mapping>

    =============================================
    上面的這些都是模型的基礎(chǔ),下面再講怎么樣配合Spring和Acegi實現(xiàn)系統(tǒng)的安全與登陸
    在Spring中Hibernate的配置只介紹不說明:
    <!-- 定義DBCP數(shù)據(jù)源 -->
     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
      <property name="driverClassName" value="com.mysql.jdbc.Driver" />
      <property name="url" value="jdbc:mysql://localhost/subject?useUnicode=true&amp;characterEncoding=gbk" />
      <property name="username" value="root" />
      <property name="password" value="" />
      <property name="maxActive" value="100" />
      <property name="maxIdle" value="30" />
      <property name="maxWait" value="1000" />
      <property name="defaultAutoCommit" value="true" />
      <property name="removeAbandoned" value="true" />
      <property name="removeAbandonedTimeout" value="60" />
     </bean>

     <!-- Hibernate -->
     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
      <property name="dataSource" ref="dataSource" />
      <property name="mappingResources">
       <list>
        <value>subject/model/User.hbm.xml</value>
       </list>
      </property>
      <property name="hibernateProperties">
       <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
       </props>
      </property>
     </bean>

     <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
      <property name="sessionFactory" ref="sessionFactory" />
     </bean>

    <!-- Dao對象 -->
    <bean id="userDao" class="subject.dao.hibernate.UserDaoImpl">
      <property name="sessionFactory" ref="sessionFactory" />
     </bean>

    <!-- 業(yè)務(wù)邏輯 -->
     <bean id="txProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
      <property name="transactionManager" ref="transactionManager" />
      <property name="transactionAttributes">
       <props>
        <prop key="save*">PROPAGATION_REQUIRED</prop>
        <prop key="remove*">PROPAGATION_REQUIRED</prop>
        <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
       </props>
      </property>
     </bean>

    <bean id="userManager" parent="txProxyTemplate">
      <property name="target">
       <bean class="subject.service.impl.UserManagerImpl">
        <property name="userDao" ref="userDao" />
       </bean>
      </property>
     </bean>

    <!-- Struts -->
     <bean name="/user" class="subject.web.action.UserAction" singleton="false">
      <property name="userManager">
       <ref bean="userManager" />
      </property>
     </bean>
    ==================
    上面具體的不用了解,無非就是調(diào)用和數(shù)據(jù)庫的操作,
    下面就要對Acegi進(jìn)行聲明了:
    我不用Ctrl+c和Ctrl+V的方式對Acegi進(jìn)行介紹,沒有意義,隨便google就一大堆
    我們想主要在這樣的系統(tǒng)中需要的安全策略都有哪些?
    1.用戶的登陸
    2.防止多個用戶登陸一個帳號
    3.用戶的注銷
    4.防止非法用戶的訪問

    我這個程序所涉及到的只有這些,下面就進(jìn)行說明:

    在web.xml的聲明:
    <!-- Acegi安全控制 Filter 配置 -->
        <filter>
            <filter-name>securityFilter</filter-name>
            <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
            <init-param>
                <param-name>targetClass</param-name>
                <param-value>org.acegisecurity.util.FilterChainProxy</param-value>
            </init-param>
        </filter>
       
        <filter-mapping>
            <filter-name>securityFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>

    Acegi通過實現(xiàn)了Filter接口的FilterToBeanProxy提供一種特殊的使用Servlet Filter的方式,它委托Spring中的Bean -- FilterChainProxy來完成過濾功能,這樣就簡化了web.xml的配置,并且利用Spring IOC的優(yōu)勢。FilterChainProxy包含了處理認(rèn)證過程的filter列表,每個filter都有各自的功能。

    <!-- ======================== FILTER CHAIN ======================= -->
     <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
      <property name="filterInvocationDefinitionSource">
       <value>
        CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
        PATTERN_TYPE_APACHE_ANT
        
        /**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,
             securityContextHolderAwareRequestFilter,exceptionTranslationFilter,filterInvocationInterceptor
       </value>
      </property>
     </bean>

    大體上先介紹一下:
    httpSessionContextIntegrationFilter:每次request前 HttpSessionContextIntegrationFilter從Session中獲取Authentication對象,在request完后, 又把Authentication對象保存到Session中供下次request使用,此filter必須其他Acegi filter前使用,使之能跨越多個請求。
    logoutFilter:用戶的注銷
    authenticationProcessingFilter:處理登陸請求
    exceptionTranslationFilter:異常轉(zhuǎn)換過濾器
    filterInvocationInterceptor:在訪問前進(jìn)行權(quán)限檢查

    這些就猶如在web.xml聲明一系列的過濾器,不過當(dāng)把他們都聲明在spring中就可以享受Spring給我們帶來的方便了。

    下面就是對這些過濾器的具體聲明:
    只對有用的地方進(jìn)行聲明,別的地方幾乎都是默許的
    <!-- ======================== FILTER ======================= -->
     <bean id="httpSessionContextIntegrationFilter"
      class="org.acegisecurity.context.HttpSessionContextIntegrationFilter" />

     <bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
      <constructor-arg value="/index.htm" />             離開后所轉(zhuǎn)向的位置
      <constructor-arg>
                <list>
                    <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
                </list>
            </constructor-arg>
      <property name="filterProcessesUrl" value="/logout.htm" />        定義用戶注銷的地址,
     </bean>

    下面的這個過濾器,我們根據(jù)自己的需求有了自己的實現(xiàn):

     <bean id="authenticationProcessingFilter" class="subject.web.filter.UserAuthenticationProcessingFilter">
      <property name="authenticationManager" ref="authenticationManager"/>  下面會介紹的用來起到認(rèn)證管理的作用
      <property name="authenticationFailureUrl" value="/login.htm?error=wrong"/>  登陸失敗的地址
      <property name="defaultTargetUrl" value="/login.htm"/>       登陸成功的地址
      <property name="filterProcessesUrl" value="/j_security_check"/>      登陸請求的地址
      <property name="userManager" ref="userManager"/>        自己添加的屬性,這樣就可以訪問到我們的業(yè)務(wù)邏輯
      <property name="exceptionMappings">   出現(xiàn)異常所對應(yīng)的地址
                <value>
                    org.acegisecurity.AuthenticationException=/login.htm?error=fail     登陸失敗                org.acegisecurity.concurrent.ConcurrentLoginException=/login.htm?error=too        已登陸了
                </value>
            </property>
     </bean>
     
     <bean id="securityContextHolderAwareRequestFilter" class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter"/>

     <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
      <property name="authenticationEntryPoint">
       <bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
        <property name="loginFormUrl" value="/login.htm?error=please"/>//如果用戶沒登陸就想訪問,先到這里登陸吧
        <property name="forceHttps" value="false"/>
       </bean>
      </property>
     </bean>
     
     <bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
      <property name="authenticationManager" ref="authenticationManager"/>       認(rèn)證服務(wù)
      <property name="accessDecisionManager">
       <bean class="org.acegisecurity.vote.AffirmativeBased">
        <property name="allowIfAllAbstainDecisions" value="false"/>
        <property name="decisionVoters">
         <list>
          <bean class="org.acegisecurity.vote.RoleVoter">
                        <property name="rolePrefix" value=""/>         //這里定義數(shù)據(jù)庫中存放的角色和我們在這里聲明的角色間是否需要加個前綴?我沒加
                    </bean>
         </list>
        </property>
       </bean>
      </property>
      <property name="objectDefinitionSource">
                <value>
                    PATTERN_TYPE_APACHE_ANT
                   
                    /admin.htm*=a         這里就是數(shù)據(jù)庫中對應(yīng)的tyep a
                    /student*=s           由于沒有前綴和數(shù)據(jù)庫里一樣
                    /teacher*=t
                </value>
            </property>
     </bean>
     
     <bean id="loggerListener"
              class="org.acegisecurity.event.authentication.LoggerListener"/>       記錄事件

    下面就要說明我們的認(rèn)證服務(wù)了,其起到的關(guān)鍵作用就是用來保證用戶登陸身份的驗證:

    它將驗證的功能委托給多個Provider,并通過遍歷Providers, 以保證獲取不同來源的身份認(rèn)證,若某個Provider能成功確認(rèn)當(dāng)前用戶的身份,authenticate()方法會返回一個完整的包含用戶授權(quán)信息的Authentication對象,否則會拋出一個AuthenticationException。

    先聲明一個管理器吧,在上面的過濾器中都已經(jīng)用到過了
    <!-- ======================== AUTHENTICATION ======================= -->
     <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
      <property name="providers">
       <list>
        <ref local="daoAuthenticationProvider" />   我僅僅用到 從數(shù)據(jù)庫中讀取用戶信息驗證身份
       </list>
      </property>
      <property name="sessionController">
       <bean id="concurrentSessionController"
        class="org.acegisecurity.concurrent.ConcurrentSessionControllerImpl">
        <property name="maximumSessions">
         <value>1</value>每個用戶同時登陸一位
        </property>
        <property name="sessionRegistry">
         <bean id="sessionRegistry" class="org.acegisecurity.concurrent.SessionRegistryImpl" />
        </property>
        <property name="exceptionIfMaximumExceeded" value="true" />
       </bean>
      </property>
     </bean>
     來實現(xiàn)唯一的一個Provider,從數(shù)據(jù)庫驗證身份
     <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
      <property name="userDetailsService">
       <bean id="jdbcDaoImpl"
                class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">
              <property name="dataSource" ref="dataSource"/>
              <property name="usersByUsernameQuery">
                  <value>
                      select user,password,about from user where user = ?        查找用戶的查詢語句,只需要把你數(shù)據(jù)庫中的用戶和密碼以及enable相對應(yīng)上就行
                  </value>
              </property>
              <property name="authoritiesByUsernameQuery">
                  <value>
                      select user,type from user where user = ?           這里就是把用戶和權(quán)限對應(yīng)上,在appfuse中用的兩個表,我都放一個表里了,所以就用這一個就行問題的關(guān)鍵是要讓它能找到兩個字段,構(gòu)成一個對象
                  </value>
              </property>
          </bean>
      </property>
      <property name="userCache"> 緩存都這么寫:
       <bean class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
        <property name="cache">
         <bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
          <property name="cacheManager">
           <bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
          </property>
          <property name="cacheName" value="userCache"/>
         </bean>
        </property>
       </bean>
      </property>
     </bean>

    ==============
    對于上面登陸請求的處理器我借鑒了springSide,實現(xiàn)的方法如下:
    package subject.web.filter;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;

    import org.acegisecurity.Authentication;
    import org.acegisecurity.context.SecurityContext;
    import org.acegisecurity.context.SecurityContextHolder;
    import org.acegisecurity.ui.webapp.AuthenticationProcessingFilter;
    import org.acegisecurity.userdetails.UserDetails;

    import subject.Constants;
    import subject.model.User;
    import subject.service.UserManager;

    public class UserAuthenticationProcessingFilter extends
      AuthenticationProcessingFilter
    {
     private UserManager userManager;

     public void setUserManager( UserManager userManager )
     {
      this.userManager = userManager;
     }

     protected boolean requiresAuthentication( HttpServletRequest request ,
       HttpServletResponse response )
     {
      boolean requiresAuth = super.requiresAuthentication( request, response );
      HttpSession httpSession = null;
      try
      {
       httpSession = request.getSession( false );
      }
      catch ( IllegalStateException ignored )
      {
      }
      if ( httpSession != null )
      {
       if ( httpSession.getAttribute( Constants.USER ) == null )
       {
        if ( !requiresAuth )
        {
         SecurityContext sc = SecurityContextHolder.getContext();
         Authentication auth = sc.getAuthentication();
         if ( auth != null
           && auth.getPrincipal() instanceof UserDetails )
         {
          UserDetails ud = (UserDetails) auth.getPrincipal();//上面聲明的sql無非就是要包裝成這個對象
          User user = userManager.getUser( ud.getUsername() );從業(yè)務(wù)邏輯里找到用戶,放到session里
          httpSession.setAttribute( Constants.USER, user );
         }
        }
       }
      }
      return requiresAuth;
     }
    }

    在看看我的login.htm在登陸成功時是怎么工作的吧?
    public class UserAction extends BaseAction
    {
     private UserManager mgr;

     public void setUserManager( UserManager mgr )
     {
      this.mgr = mgr;
     }

     public ActionForward login( ActionMapping mapping , ActionForm form ,
       HttpServletRequest request , HttpServletResponse response )
       throws Exception
     {
      User user = (User) getSessionObject( request, Constants.USER );
      ActionMessages msg = new ActionMessages();
      if ( user != null )
      {
       return new ActionForward(  user.getType() + ".htm", true );成功就去type.htm
      }
      else
      {
       String error = getParameter( request, Constants.ERROR );
       if ( error != null )對于不同的錯誤,都加以提示
       {
        if ( error.equalsIgnoreCase( "wrong" ) )
         msg.add( "msg", new ActionMessage( "fail.login.wrong" ) );
        else if ( error.equalsIgnoreCase( "too" ) )
         msg.add( "msg", new ActionMessage( "fail.login.too" ) );
        else if ( error.equalsIgnoreCase( "fail" ) )
         msg.add( "msg", new ActionMessage( "fail.login.fail" ) );
        else
         msg.add( "msg", new ActionMessage( "fail.login.please" ) );
       }
       else
        msg.add( "msg", new ActionMessage( "fail.login.please" ) );
      }
      saveErrors( request, msg );
      return mapping.findForward( "fail" );
     }

    }

    當(dāng)然,Acegi需要介紹的東西太多了,我只把我這次認(rèn)為有必要解釋的東西寫在了上面讓大家來參考,作為能google到的東西,比如對于認(rèn)證的方式還有很多,我就沒有詳細(xì)的介紹,在學(xué)習(xí)Acegi過程中,把它自帶的例子弄清楚很關(guān)鍵,希望大家一起學(xué)習(xí)一起共勉!

    posted on 2008-04-21 17:57 xyz 閱讀(367) 評論(0)  編輯  收藏 所屬分類: 網(wǎng)絡(luò)文摘

    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    留言簿

    隨筆檔案(1)

    文章分類(44)

    文章檔案(46)

    收藏夾(1)

    Adobe

    AOP

    API

    appServer

    BI

    c

    • c-free
    • codeblocks
    • codelite
    • CodeLite IDE 是一個強(qiáng)大的開源,跨平臺的 C/C++整合開發(fā)環(huán)境. 支持包括 Windows、Linux 和 Mac 系統(tǒng)下運行
    • codelite官網(wǎng)
    • dev-c++
    • Dev-C++是一個C&C++開發(fā)工具,它是一款自由軟件,遵守GPL協(xié)議。
    • GCC
    • GCC 原名為 GNU C 語言編譯器(GNU C Compiler),因為它原本只能處理 C語言。GCC 很快地擴(kuò)展,變得可處理 C++。之后也變得可處理 Fortran、Pascal、Objective-C、Java, 以及 Ada 與其他語言。

    Cache

    CMS

    DB

    eclipse

    FreeMarker

    hibernate

    html5

    ibatis

    java

    jquery

    js

    json

    Linux

    Log

    mail server

    mobile

    mysql

    oauth

    openID

    other

    PHP

    portal

    report

    Scheduler

    schema

    Security

    SOA

    spring

    struts

    UI原型設(shè)計

    w3c

    Wap

    webservice

    xml

    供應(yīng)鏈管理

    博客鏈接

    好網(wǎng)站

    工作流

    開源網(wǎng)

    招聘

    插件下載

    操作系統(tǒng)

    構(gòu)建可伸縮的系統(tǒng)

    構(gòu)建工具

    測試

    游戲

    源碼托管

    經(jīng)營

    資源

    金融/財務(wù)

    搜索

    •  

    最新評論

    主站蜘蛛池模板: 中文字幕免费在线看电影大全| 亚洲中文字幕无码永久在线| 中文字幕无码不卡免费视频| 114级毛片免费观看| 99精品国产成人a∨免费看| 日韩av无码久久精品免费| 久久99精品国产免费观看| 精品无码国产污污污免费网站| 嫩草成人永久免费观看| 久久久久国产精品免费免费不卡| 久久久久久一品道精品免费看| 久久永久免费人妻精品| 91精品视频在线免费观看| 88xx成人永久免费观看| free哆啪啪免费永久| 野花高清在线观看免费完整版中文| 久久国内免费视频| 国产免费av片在线看| 青草草在线视频永久免费| 免费人成在线观看播放国产| 亚洲美日韩Av中文字幕无码久久久妻妇| 亚洲国产精品人人做人人爽| 亚洲无码黄色网址| 亚洲AV永久纯肉无码精品动漫| 亚洲黄色在线电影| 亚洲中文字幕无码中文字| 美女黄色免费网站| 久久久免费观成人影院| 久久精品视频免费看| 日韩欧毛片免费视频| 国产色爽女小说免费看| 亚洲精品国产福利一二区| 国产偷v国产偷v亚洲高清| 亚洲国产美女在线观看| 久久亚洲精品高潮综合色a片| 本道天堂成在人线av无码免费 | 免费一看一级毛片人| 在线观看亚洲天天一三视| 亚洲网站免费观看| 久久精品国产亚洲AV| 大地资源在线资源免费观看|