1. 程式人生 > >【Spring Security實戰系列】Spring Security實戰(七)

【Spring Security實戰系列】Spring Security實戰(七)

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:sec="http://www.springframework.org/schema/security"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-3.1.xsd
                        http://www.springframework.org/schema/tx
                        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
                        http://www.springframework.org/schema/security
                        http://www.springframework.org/schema/security/spring-security.xsd">


    <!-- 配置不過濾的資源(靜態資源及登入相關).是忽略攔截某些資源的意思,主要是針對靜態資源 -->
    <http pattern="/**/*.css" security="none"></http>
    <http pattern="/**/*.jpg" security="none"></http>
    <http pattern="/**/*.jpeg" security="none"></http>
    <http pattern="/**/*.gif" security="none"></http>
    <http pattern="/**/*.png" security="none"></http>
    <http pattern="/js/*.js" security="none"></http>

    <http pattern="/login.jsp" security="none"></http>
    <http pattern="/getCode" security="none" /><!-- 不過濾驗證碼 -->
    <http pattern="/test/**" security="none"></http><!-- 不過濾測試內容 -->

    <http auto-config="false" entry-point-ref="loginUrlAuthenticationEntryPoint">

        <!--<intercept-url pattern="/login.jsp" access="permitAll" />-->
        <!-- 表示訪問app.jsp時,需要ROLE_SERVICE許可權 -->
        <!--<intercept-url pattern="/adminPage.jsp" access="hasRole('ROLE_ADMIN')"></intercept-url>-->
        <!--表示訪問任何資源都需要ROLE_ADMIN許可權。-->
        <!-- <intercept-url pattern="/**" access="hasRole('ROLE_USER')"></intercept-url>-->

        <!--
            登陸頁面肯定是不能攔截的,任何人都應該可以訪問,
            <intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />配置表示允許匿名使用者訪問,
            就是不用身份都可以訪問;
            還有另一種配置方式:<http pattern="/login.jsp" security="none"></http>,這種配置達到的目的都是一樣的。
        -->

        <!--
            form-login這個標籤是配置登陸頁面的,其中的屬性login-page是配置登陸頁面的,
            default-target-url配置登陸成功後跳轉到的頁面,
            authentication-failure-url配置認證失敗後的跳轉頁面。

            form-login標籤中還有一個特別要注意的屬性use-expressions,如果設定為true,
            這配置access就要做相應的改變,否則專案啟動的時候會報錯。
            如果use-expressns="true"時,則表示改為 SpEL 表示式。 SpEL 允許使用特定的訪問控制規則表示式語言。
            與簡單的字串如 ROLE_USER 不同,配置檔案可以指明表示式語言觸發方法呼叫、引用系統屬性、計算機值等等。
            如 :<intercept-url pattern="/login.jsp" access="permitAll" />
        -->
        <!--<form-login login-page="/login.jsp" default-target-url="/index.jsp"
                    authentication-failure-url="/login.jsp?error=true"></form-login>-->

        <!--
            logout這個標籤用來配置退出或者登出,其中的屬性invalidate-session,
            配置否是要清除session,logout-success-url配置登出成功後的跳轉頁面,
            logout-url提交退出或者登出的地址,因此我們在配置退出或者登出的時候,
            只需要將url設定為/j_spring_security_logout即可,這個地址也是security內部實現了的。
        -->
        <logout invalidate-session="true" logout-success-url="/login.jsp"
                logout-url="/j_spring_security_logout"></logout>

        <custom-filter ref="myUsernamePasswordAuthenticationFilter" position="FORM_LOGIN_FILTER"></custom-filter>

        <!--========================新增內容==========start=============================================-->
        <!--替換預設REMEMBER_ME_FILTER-->
        <custom-filter ref="rememberMeFilter" position="REMEMBER_ME_FILTER"/>
        <!--========================新增內容=======================================================-->

        <!--
            通過配置custom-filter來增加過濾器,
            before="FILTER_SECURITY_INTERCEPTOR"表示在Springsecurity預設的過濾器之前執行
        -->
        <custom-filter ref="filterSecurityInterceptor" before="FILTER_SECURITY_INTERCEPTOR"></custom-filter>

        <!-- max-sessions只容許一個賬號登入,error-if-maximum-exceeded 後面賬號登入後踢出前一個賬號,
              expired-url session過期跳轉介面
              如果concurrency-control標籤配置了error-if-maximum-exceeded="true",max-sessions="1",
              那麼第二次登入時,是登入不了的。如果error-if-maximum-exceeded="false",
              那麼第二次是能夠登入到系統的,但是第一個登入的賬號再次發起請求時,會跳轉到expired-url配置的url中-->
        <session-management session-authentication-error-url="/login.jsp">
            <concurrency-control max-sessions="1" error-if-maximum-exceeded="false"
                                 expired-url="/login.jsp" session-registry-ref="sessionRegistry" />
        </session-management>

        <expression-handler ref="webexpressionHandler" ></expression-handler>

    </http>

    <beans:bean id="loginUrlAuthenticationEntryPoint"
                class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
        <beans:property name="loginFormUrl" value="/login.jsp"></beans:property>
    </beans:bean>

    <!-- 匯入資料來源 -->
    <beans:import resource="applicationContext-dataSource.xml"></beans:import>

    <beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>
    <!--配置web端使用許可權控制-->
    <beans:bean id="webexpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler"/>


    <beans:bean id="bulider" class="cn.quan.ssm.sec.JdbcRequestMapBulider">
        <beans:property name="dataSource" ref="mysqlDataSource"></beans:property>
        <beans:property name="resourceQuery" value="select re.res_string,r.`name` from role r,resc re,resc_role rr where r.id=rr.role_id and re.id=rr.resc_id" />
    </beans:bean>

    <!--配置自定義的過濾器:配置MyUsernamePasswordAuthenticationFilter並將其加入到FilterChain中去-->
    <beans:bean id="myUsernamePasswordAuthenticationFilter"
                class="cn.quan.ssm.sec.dao.MyUsernamePasswordAuthenticationFilter">
        <!--filterProcessesUrl屬性為登陸的過濾的地址-->
        <beans:property name="filterProcessesUrl" value="/j_spring_security_check" />
        <!--authenticationManager為authentication-manager標籤中配置的-->
        <beans:property name="authenticationManager" ref="authenticationManager" />
        <!--authenticationSuccessHandler為驗證成功後跳轉的處理器-->
        <beans:property name="authenticationSuccessHandler" ref="loginLogAuthenticationSuccessHandler" />
        <!--authenticationFailureHandler為驗證失敗的處理器-->
        <beans:property name="authenticationFailureHandler" ref="simpleUrlAuthenticationFailureHandler" />
        <!--========================新增內容==========start=============================================-->
        <beans:property name="rememberMeServices" ref="rememberMeServices" />
        <!--========================新增內容==========end=============================================-->
    </beans:bean>

    <beans:bean id="loginLogAuthenticationSuccessHandler"
                class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
        <beans:property name="targetUrlParameter" value="/index.jsp"></beans:property>
    </beans:bean>

    <beans:bean id="simpleUrlAuthenticationFailureHandler"
                class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
        <beans:property name="defaultFailureUrl" value="/login.jsp"></beans:property>
    </beans:bean>


    <beans:bean id="filterSecurityInterceptor"
                class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
        <!-- 使用者擁有的許可權 -->
        <beans:property name="accessDecisionManager" ref="accessDecisionManager" />
        <!-- 使用者是否擁有所請求資源的許可權 -->
        <beans:property name="authenticationManager" ref="authenticationManager" />
        <!-- 資源與許可權對應關係 -->
        <beans:property name="securityMetadataSource" ref="securityMetadataSource" />
    </beans:bean>

    <!--授權管理器:acl領域模型-->
    <beans:bean id="accessDecisionManager" class="cn.quan.ssm.sec.dao.MyAccessDecisionManager" />

    <!--認證管理-->
    <authentication-manager alias="authenticationManager">
        <authentication-provider user-service-ref="userDetailsService">
        </authentication-provider>
        <!--========================新增內容==========start=============================================-->
        <!-- 記住密碼 -->
        <authentication-provider ref="rememberMeAuthenticationProvider"></authentication-provider>
        <!--========================新增內容==========end=============================================-->
    </authentication-manager>

    <!--========================新增內容==========start=============================================-->
    <!--
        說明:dataSource就是連線資料庫的資料來源;usersByUsernameQuery就是配置jdbc-user-service時候的users-by-username-query,
        這個是根據使用者名稱來查詢使用者的sql語句;同理authoritiesByUsernameQuery就是對應的authorities-by-username-query,
        這個用來根據使用者名稱查詢對應的許可權。
    -->
    <!-- 配置userDetailsService -->

    <beans:bean id="userDetailsService"
                class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
        <beans:property name="usersByUsernameQuery"
                        value="select username,password,status as enabled from user where username = ?" />
        <beans:property name="authoritiesByUsernameQuery"
                        value="select user.username,role.name from user,role,user_role
                                    where user.id=user_role.user_id and
                                    user_role.role_id=role.id and user.username=?" />
        <beans:property name="dataSource" ref="mysqlDataSource" />
    </beans:bean>

    <!--配置rememberMe的過濾器: Remember-Me 對應的 Filter-->
    <beans:bean id="rememberMeFilter"
                class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
        <beans:property name="rememberMeServices" ref="rememberMeServices" />
        <beans:property name="authenticationManager" ref="authenticationManager" />
    </beans:bean>
    <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~基於簡單加密的方式~~start~~~~~~不存資料庫~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
    <!-- rememberService -->
    <!-- RememberMeServices 的實現 -->
    <beans:bean id="rememberMeServices"
                class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
        <beans:property name="userDetailsService" ref="userDetailsService" />
        <beans:property name="key" value="zmc" />
        <!-- 指定 request 中包含的使用者是否選擇了記住我的引數名 -->
        <beans:property name="parameter" value="rememberMe"/>
    </beans:bean>
    <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~基於簡單加密的方式~~end~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->


    <!-- 記住密碼 -->
    <!-- key 值需與對應的 RememberMeServices 保持一致 -->
    <beans:bean id="rememberMeAuthenticationProvider"
                class="org.springframework.security.authentication.RememberMeAuthenticationProvider" >
        <beans:property name="key" value="zmc" />
    </beans:bean>
    <!--========================新增內容==========end=============================================-->

    <!--自定義的切入點-->
    <beans:bean id="securityMetadataSource"
                class="cn.quan.ssm.sec.dao.MyFilterInvocationSecurityMetadataSource">
        <beans:property name="bulider" ref="bulider"></beans:property>
    </beans:bean>

</beans:beans>