<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
    還以我傳統的例子為例:
    畢業設計選題系統,三種角色:教師,學生,管理員,我想讓他們的登陸都在一個界面下自動識別,而無需進行身份選擇,登陸后,他們將分別到各自的admin.jsp,stu.jsp,teacher.jsp
    在數據庫中的表結構如下(很多屬性略):
    id--- user---password--type---about

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

    在model里,我們采用了繼承關系:

    父類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(); //這個是用來反映用戶角色的關鍵函數,在子類實現,從而實現多態
    }

    子類的實現:
    ======================
    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;         //學生的班級
     private String sn;             //學生的學號

    //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;
     }
    }

    對于三者所共有的屬性在數據庫里,都存在一個字段,而依據不同的角色擁有不同的含義,學生的班級則存放在了about里,只要學生有班級,他就able,否則就enable了!而管理員和教師則默認為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>

    =============================================
    上面的這些都是模型的基礎,下面再講怎么樣配合Spring和Acegi實現系統的安全與登陸
    在Spring中Hibernate的配置只介紹不說明:
    <!-- 定義DBCP數據源 -->
     <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>

    <!-- 業務邏輯 -->
     <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>
    ==================
    上面具體的不用了解,無非就是調用和數據庫的操作,
    下面就要對Acegi進行聲明了:
    我不用Ctrl+c和Ctrl+V的方式對Acegi進行介紹,沒有意義,隨便google就一大堆
    我們想主要在這樣的系統中需要的安全策略都有哪些?
    1.用戶的登陸
    2.防止多個用戶登陸一個帳號
    3.用戶的注銷
    4.防止非法用戶的訪問

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

    在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通過實現了Filter接口的FilterToBeanProxy提供一種特殊的使用Servlet Filter的方式,它委托Spring中的Bean -- FilterChainProxy來完成過濾功能,這樣就簡化了web.xml的配置,并且利用Spring IOC的優勢。FilterChainProxy包含了處理認證過程的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:異常轉換過濾器
    filterInvocationInterceptor:在訪問前進行權限檢查

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

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

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

    下面的這個過濾器,我們根據自己的需求有了自己的實現:

     <bean id="authenticationProcessingFilter" class="subject.web.filter.UserAuthenticationProcessingFilter">
      <property name="authenticationManager" ref="authenticationManager"/>  下面會介紹的用來起到認證管理的作用
      <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"/>        自己添加的屬性,這樣就可以訪問到我們的業務邏輯
      <property name="exceptionMappings">   出現異常所對應的地址
                <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"/>       認證服務
      <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=""/>         //這里定義數據庫中存放的角色和我們在這里聲明的角色間是否需要加個前綴?我沒加
                    </bean>
         </list>
        </property>
       </bean>
      </property>
      <property name="objectDefinitionSource">
                <value>
                    PATTERN_TYPE_APACHE_ANT
                   
                    /admin.htm*=a         這里就是數據庫中對應的tyep a
                    /student*=s           由于沒有前綴和數據庫里一樣
                    /teacher*=t
                </value>
            </property>
     </bean>
     
     <bean id="loggerListener"
              class="org.acegisecurity.event.authentication.LoggerListener"/>       記錄事件

    下面就要說明我們的認證服務了,其起到的關鍵作用就是用來保證用戶登陸身份的驗證:

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

    先聲明一個管理器吧,在上面的過濾器中都已經用到過了
    <!-- ======================== AUTHENTICATION ======================= -->
     <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
      <property name="providers">
       <list>
        <ref local="daoAuthenticationProvider" />   我僅僅用到 從數據庫中讀取用戶信息驗證身份
       </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>
     來實現唯一的一個Provider,從數據庫驗證身份
     <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 = ?        查找用戶的查詢語句,只需要把你數據庫中的用戶和密碼以及enable相對應上就行
                  </value>
              </property>
              <property name="authoritiesByUsernameQuery">
                  <value>
                      select user,type from user where user = ?           這里就是把用戶和權限對應上,在appfuse中用的兩個表,我都放一個表里了,所以就用這一個就行問題的關鍵是要讓它能找到兩個字段,構成一個對象
                  </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,實現的方法如下:
    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() );從業務邏輯里找到用戶,放到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" );
     }

    }

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

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

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

    留言簿

    隨筆檔案(1)

    文章分類(44)

    文章檔案(46)

    收藏夾(1)

    Adobe

    AOP

    API

    appServer

    BI

    c

    • c-free
    • codeblocks
    • codelite
    • CodeLite IDE 是一個強大的開源,跨平臺的 C/C++整合開發環境. 支持包括 Windows、Linux 和 Mac 系統下運行
    • codelite官網
    • dev-c++
    • Dev-C++是一個C&C++開發工具,它是一款自由軟件,遵守GPL協議。
    • GCC
    • GCC 原名為 GNU C 語言編譯器(GNU C Compiler),因為它原本只能處理 C語言。GCC 很快地擴展,變得可處理 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原型設計

    w3c

    Wap

    webservice

    xml

    供應鏈管理

    博客鏈接

    好網站

    工作流

    開源網

    招聘

    插件下載

    操作系統

    構建可伸縮的系統

    構建工具

    測試

    • IETest
    • IE官網
    • OpenSTA
    • Siege
    • Siege是一個壓力測試和評測工具,設計用于WEB開發這評估應用在壓力下的承受能力

    游戲

    源碼托管

    經營

    資源

    金融/財務

    搜索

    •  

    最新評論

    主站蜘蛛池模板: 亚洲乱人伦中文字幕无码| 97国免费在线视频| 亚洲国产一区明星换脸| 三级网站在线免费观看| 亚洲国产理论片在线播放| 国产成人免费a在线资源| 99re6在线视频精品免费| 亚洲国产成人精品青青草原| 日本特黄特黄刺激大片免费| 免费在线中文日本| 久久亚洲精品无码av| 亚洲AV成人片色在线观看| 无码国模国产在线观看免费| 久久免费观看国产99精品| 亚洲第一街区偷拍街拍| 日韩亚洲人成在线综合日本| 毛片视频免费观看| 国产黄在线观看免费观看不卡| 亚洲综合小说久久另类区| 亚洲成A人片在线观看无码3D| 一个人看的www免费视频在线观看 一个人免费视频观看在线www | 久久久受www免费人成| 亚洲综合国产成人丁香五月激情 | 国产亚洲欧美在线观看| 亚洲中文字幕久在线| 亚洲乱码无码永久不卡在线| 欧美日韩国产免费一区二区三区 | 亚洲国产精品碰碰| 成人黄软件网18免费下载成人黄18免费视频| 一个人看的免费高清视频日本| 亚洲一区在线观看视频| 久久国产亚洲精品麻豆| 亚洲?v无码国产在丝袜线观看 | 日韩a级毛片免费观看| 久久成人国产精品免费软件| 中文字幕成人免费高清在线视频| 亚洲第一第二第三第四第五第六| 亚洲国产成人手机在线电影bd| 亚洲va在线va天堂va不卡下载 | 亚洲熟女精品中文字幕| 亚洲成人免费网址|