1. 程式人生 > >springmvc+shiro+maven 實現登入與許可權授權

springmvc+shiro+maven 實現登入與許可權授權

[java] view plain copy print?
  1. <!– 配置shiro的核心攔截器 –>    
  2.    <filter>    
  3.         <filter-name>shiroFilter</filter-name>    
  4.         <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>    
  5.     </filter>    
  6.     <filter-mapping>    
  7.         <filter-name>shiroFilter</filter-name>    
  8.         <url-pattern>/admin/*</url-pattern>    
  9.     </filter-mapping>    
<!-- 配置shiro的核心攔截器 -->  
   <filter>  
        <filter-name>shiroFilter</filter-name>  
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
    </filter>  
    <filter-mapping>  
        <filter-name>shiroFilter</filter-name>  
        <url-pattern>/admin/*</url-pattern>  
    </filter-mapping>  

3: springmvc中對shiro配置

[java] view plain copy print?
  1. <beans xmlns=“http://www.springframework.org/schema/beans”
  2.     xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:mvc=“http://www.springframework.org/schema/mvc”
  3.     xmlns:context=”http://www.springframework.org/schema/context”
  4.     xmlns:aop=”http://www.springframework.org/schema/aop”
     xmlns:tx=“http://www.springframework.org/schema/tx”
  5.     xsi:schemaLocation=”http://www.springframework.org/schema/beans   
  6.         http://www.springframework.org/schema/beans/spring-beans-3.2.xsd   
  7.         http://www.springframework.org/schema/mvc   
  8.         http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd   
  9.         http://www.springframework.org/schema/context   
  10.         http://www.springframework.org/schema/context/spring-context-3.2.xsd   
  11.         http://www.springframework.org/schema/aop   
  12.         http://www.springframework.org/schema/aop/spring-aop-3.2.xsd   
  13.         http://www.springframework.org/schema/tx   
  14.         http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ”>  
  15.     <!– web.xml中shiro的filter對應的bean –>    
  16.     <bean id=”shiroFilter”class=“org.apache.shiro.spring.web.ShiroFilterFactoryBean”>    
  17.         <!– 管理器,必須設定 –>    
  18.         <property name=”securityManager” ref=“securityManager” />    
  19.         <!– 攔截到,跳轉到的地址,通過此地址去認證 –>    
  20.         <property name=”loginUrl” value=“/admin/login.do” />    
  21.         <!– 認證成功統一跳轉到/admin/index.do,建議不配置,shiro認證成功自動到上一個請求路徑 –>    
  22.         <property name=”successUrl” value=“/admin/index.do” />    
  23.         <!– 通過unauthorizedUrl指定沒有許可權操作時跳轉頁面 –>    
  24.         <property name=”unauthorizedUrl” value=“/refuse.jsp” />    
  25.         <!– 自定義filter,可用來更改預設的表單名稱配置 –>    
  26.         <property name=”filters”>    
  27.             <map>    
  28.                 <!– 將自定義 的FormAuthenticationFilter注入shiroFilter中 –>    
  29.                 <entry key=”authc” value-ref=“formAuthenticationFilter” />    
  30.             </map>    
  31.         </property>    
  32.         <property name=”filterChainDefinitions”>    
  33.             <value>    
  34.                 <!– 對靜態資源設定匿名訪問 –>    
  35.                 /images/** = anon    
  36.                 /js/** = anon    
  37.                 /styles/** = anon    
  38.                 <!– 驗證碼,可匿名訪問 –>    
  39.                 /validatecode.jsp = anon    
  40.                 <!– 請求 logout.do地址,shiro去清除session –>    
  41.                 /admin/logout.do = logout    
  42.                 <!–商品查詢需要商品查詢許可權 ,取消url攔截配置,使用註解授權方式 –>    
  43.                 <!– /items/queryItems.action = perms[item:query] /items/editItems.action     
  44.                     = perms[item:edit] –>    
  45.                 <!– 配置記住我或認證通過可以訪問的地址 –>    
  46.                 /welcome.jsp = user    
  47.                 /admin/index.do = user    
  48.                 <!– /** = authc 所有url都必須認證通過才可以訪問 –>    
  49.                 /** = authc    
  50.             </value>    
  51.         </property>    
  52.     </bean>    
  53.     <!– securityManager安全管理器 –>    
  54.     <bean id=”securityManager”class=“org.apache.shiro.web.mgt.DefaultWebSecurityManager”>    
  55.         <property name=”realm” ref=“customRealm” />    
  56.         <!– 注入快取管理器 –>    
  57.         <property name=”cacheManager” ref=“cacheManager” />    
  58.         <!– 注入session管理器 –>    
  59.         <!– <property name=”sessionManager” ref=“sessionManager” /> –>    
  60.         <!– 記住我 –>    
  61.         <property name=”rememberMeManager” ref=“rememberMeManager” />    
  62.     </bean>    
  63.     <!– 自定義realm –>    
  64.     <bean id=”customRealm”class=“com.zhijianj.stucheck.shiro.CustomRealm”>    
  65.         <!– 將憑證匹配器設定到realm中,realm按照憑證匹配器的要求進行雜湊 –>    
  66.         <!– <property name=”credentialsMatcher” ref=“credentialsMatcher” /> –>    
  67.     </bean>    
  68.     <!– 憑證匹配器 –>    
  69.     <bean id=”credentialsMatcher”
  70.         class=“org.apache.shiro.authc.credential.HashedCredentialsMatcher”>    
  71.         <!– 選用MD5雜湊演算法 –>    
  72.         <property name=”hashAlgorithmName” value=“md5” />    
  73.         <!– 進行一次加密 –>    
  74.         <property name=”hashIterations” value=“1” />    
  75.     </bean>    
  76.     <!– 自定義form認證過慮器 –>    
  77.     <!– 基於Form表單的身份驗證過濾器,不配置將也會註冊此過慮器,表單中的使用者賬號、密碼及loginurl將採用預設值,建議配置 –>    
  78.     <!– 可通過此配置,判斷驗證碼 –>    
  79.     <bean id=”formAuthenticationFilter”
  80.         class=“com.zhijianj.stucheck.shiro.CustomFormAuthenticationFilter ”>    
  81.         <!– 表單中賬號的input名稱,預設為username –>    
  82.         <property name=”usernameParam” value=“username” />    
  83.         <!– 表單中密碼的input名稱,預設為password –>    
  84.         <property name=”passwordParam” value=“password” />    
  85.         <!– 記住我input的名稱,預設為rememberMe –>    
  86.         <property name=”rememberMeParam” value=“rememberMe” />    
  87.     </bean>    
  88.     <!– 會話管理器 –>    
  89.     <bean id=”sessionManager”
  90.         class=“org.apache.shiro.web.session.mgt.DefaultWebSessionManager”>    
  91.         <!– session的失效時長,單位毫秒 –>    
  92.         <property name=”globalSessionTimeout” value=“600000” />    
  93.         <!– 刪除失效的session –>    
  94.         <property name=”deleteInvalidSessions” value=“true” />    
  95.     </bean>    
  96.     <!– 快取管理器 –>    
  97.     <bean id=”cacheManager”class=“org.apache.shiro.cache.ehcache.EhCacheManager”>    
  98.         <property name=”cacheManagerConfigFile” value=“classpath:shiro-ehcache.xml” />    
  99.     </bean>    
  100.     <!– rememberMeManager管理器,寫cookie,取出cookie生成使用者資訊 –>    
  101.     <bean id=”rememberMeManager”class=“org.apache.shiro.web.mgt.CookieRememberMeManager”>    
  102.         <property name=”cookie” ref=“rememberMeCookie” />    
  103.     </bean>    
  104.     <!– 記住我cookie –>    
  105.     <bean id=”rememberMeCookie”class=“org.apache.shiro.web.servlet.SimpleCookie”>    
  106.         <!– rememberMe是cookie的名字 –>    
  107.         <constructor-arg value=”rememberMe” />    
  108.         <!– 記住我cookie生效時間30天 –>    
  109.         <property name=”maxAge” value=“2592000” />    
  110.     </bean>    
  111. </beans>    
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"  
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans   
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd   
        http://www.springframework.org/schema/mvc   
        http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd   
        http://www.springframework.org/schema/context   
        http://www.springframework.org/schema/context/spring-context-3.2.xsd   
        http://www.springframework.org/schema/aop   
        http://www.springframework.org/schema/aop/spring-aop-3.2.xsd   
        http://www.springframework.org/schema/tx   
        http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">  

    <!-- web.xml中shiro的filter對應的bean -->  
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
        <!-- 管理器,必須設定 -->  
        <property name="securityManager" ref="securityManager" />  
        <!-- 攔截到,跳轉到的地址,通過此地址去認證 -->  
        <property name="loginUrl" value="/admin/login.do" />  
        <!-- 認證成功統一跳轉到/admin/index.do,建議不配置,shiro認證成功自動到上一個請求路徑 -->  
        <property name="successUrl" value="/admin/index.do" />  
        <!-- 通過unauthorizedUrl指定沒有許可權操作時跳轉頁面 -->  
        <property name="unauthorizedUrl" value="/refuse.jsp" />  
        <!-- 自定義filter,可用來更改預設的表單名稱配置 -->  
        <property name="filters">  
            <map>  
                <!-- 將自定義 的FormAuthenticationFilter注入shiroFilter中 -->  
                <entry key="authc" value-ref="formAuthenticationFilter" />  
            </map>  
        </property>  
        <property name="filterChainDefinitions">  
            <value>  
                <!-- 對靜態資源設定匿名訪問 -->  
                /images/** = anon  
                /js/** = anon  
                /styles/** = anon  
                <!-- 驗證碼,可匿名訪問 -->  
                /validatecode.jsp = anon  
                <!-- 請求 logout.do地址,shiro去清除session -->  
                /admin/logout.do = logout  
                <!--商品查詢需要商品查詢許可權 ,取消url攔截配置,使用註解授權方式 -->  
                <!-- /items/queryItems.action = perms[item:query] /items/editItems.action   
                    = perms[item:edit] -->  
                <!-- 配置記住我或認證通過可以訪問的地址 -->  
                /welcome.jsp = user  
                /admin/index.do = user  
                <!-- /** = authc 所有url都必須認證通過才可以訪問 -->  
                /** = authc  
            </value>  
        </property>  
    </bean>  

    <!-- securityManager安全管理器 -->  
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
        <property name="realm" ref="customRealm" />  
        <!-- 注入快取管理器 -->  
        <property name="cacheManager" ref="cacheManager" />  
        <!-- 注入session管理器 -->  
        <!-- <property name="sessionManager" ref="sessionManager" /> -->  
        <!-- 記住我 -->  
        <property name="rememberMeManager" ref="rememberMeManager" />  
    </bean>  

    <!-- 自定義realm -->  
    <bean id="customRealm" class="com.zhijianj.stucheck.shiro.CustomRealm">  
        <!-- 將憑證匹配器設定到realm中,realm按照憑證匹配器的要求進行雜湊 -->  
        <!-- <property name="credentialsMatcher" ref="credentialsMatcher" /> -->  
    </bean>  

    <!-- 憑證匹配器 -->  
    <bean id="credentialsMatcher"  
        class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">  
        <!-- 選用MD5雜湊演算法 -->  
        <property name="hashAlgorithmName" value="md5" />  
        <!-- 進行一次加密 -->  
        <property name="hashIterations" value="1" />  
    </bean>  

    <!-- 自定義form認證過慮器 -->  
    <!-- 基於Form表單的身份驗證過濾器,不配置將也會註冊此過慮器,表單中的使用者賬號、密碼及loginurl將採用預設值,建議配置 -->  
    <!-- 可通過此配置,判斷驗證碼 -->  
    <bean id="formAuthenticationFilter"  
        class="com.zhijianj.stucheck.shiro.CustomFormAuthenticationFilter ">  
        <!-- 表單中賬號的input名稱,預設為username -->  
        <property name="usernameParam" value="username" />  
        <!-- 表單中密碼的input名稱,預設為password -->  
        <property name="passwordParam" value="password" />  
        <!-- 記住我input的名稱,預設為rememberMe -->  
        <property name="rememberMeParam" value="rememberMe" />  
    </bean>  
    <!-- 會話管理器 -->  
    <bean id="sessionManager"  
        class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">  
        <!-- session的失效時長,單位毫秒 -->  
        <property name="globalSessionTimeout" value="600000" />  
        <!-- 刪除失效的session -->  
        <property name="deleteInvalidSessions" value="true" />  
    </bean>  
    <!-- 快取管理器 -->  
    <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">  
        <property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml" />  
    </bean>  
    <!-- rememberMeManager管理器,寫cookie,取出cookie生成使用者資訊 -->  
    <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">  
        <property name="cookie" ref="rememberMeCookie" />  
    </bean>  
    <!-- 記住我cookie -->  
    <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">  
        <!-- rememberMe是cookie的名字 -->  
        <constructor-arg value="rememberMe" />  
        <!-- 記住我cookie生效時間30天 -->  
        <property name="maxAge" value="2592000" />  
    </bean>  
</beans>  

4 :自定義Realm編碼

[java] view plain copy print?
  1. publicclass CustomRealm extends AuthorizingRealm {    
  2.     // 設定realm的名稱  
  3.     @Override
  4.     publicvoid setName(String name) {    
  5.         super.setName(“customRealm”);    
  6.     }    
  7.     @Autowired
  8.     private AdminUserService adminUserService;    
  9.     /**  
  10.      * 認證  
  11.      */
  12.     @Override
  13.     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {    
  14.         // token中包含使用者輸入的使用者名稱和密碼  
  15.         // 第一步從token中取出使用者名稱  
  16.         String userName = (String) token.getPrincipal();    
  17.         // 第二步:根據使用者輸入的userCode從資料庫查詢  
  18.         TAdminUser adminUser = adminUserService.getAdminUserByUserName(userName);    
  19.         // 如果查詢不到返回null  
  20.         if (adminUser == null) {//  
  21.             returnnull;    
  22.         }    
  23.         // 獲取資料庫中的密碼  
  24.         String password = adminUser.getPassword();    
  25.         /**  
  26.          * 認證的使用者,正確的密碼  
  27.          */
  28.         AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(adminUser, password, this.getName());    
  29.                //MD5 加密+加鹽+多次加密  
  30. //<span style=”color:#ff0000;”>SimpleAuthenticationInfo authcInfo = new SimpleAuthenticationInfo(adminUser, password,ByteSource.Util.bytes(salt), this.getName());</span>  
  31.         return authcInfo;    
  32.     }    
  33.     /**  
  34.      * 授權,只有成功通過<span style=”font-family: Arial, Helvetica, sans-serif;”>doGetAuthenticationInfo方法的認證後才會執行。</span>  
  35.      */
  36.     @Override
  37.     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {    
  38.         // 從 principals獲取主身份資訊  
  39.         // 將getPrimaryPrincipal方法返回值轉為真實身份型別(在上邊的doGetAuthenticationInfo認證通過填充到SimpleAuthenticationInfo中身份型別),  
  40.         TAdminUser activeUser = (TAdminUser) principals.getPrimaryPrincipal();    
  41.         // 根據身份資訊獲取許可權資訊  
  42.         // 從資料庫獲取到許可權資料  
  43.         TAdminRole adminRoles = adminUserService.getAdminRoles(activeUser);    
  44.         // 單獨定一個集合物件  
  45.         List<String> permissions = new ArrayList<String>();    
  46.         if (adminRoles != null) {    
  47.             permissions.add(adminRoles.getRoleKey());    
  48.         }    
  49.         // 查到許可權資料,返回授權資訊(要包括 上邊的permissions)  
  50.         SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();    
  51.         // 將上邊查詢到授權資訊填充到simpleAuthorizationInfo物件中  
  52.         simpleAuthorizationInfo.addStringPermissions(permissions);    
  53.         return simpleAuthorizationInfo;    
  54.     }    
  55.     // 清除快取  
  56.     publicvoid clearCached() {    
  57.         PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();    
  58.         super.clearCache(principals);    
  59.     }    
  60. }    
public class CustomRealm extends AuthorizingRealm {  
    // 設定realm的名稱  
    @Override  
    public void setName(String name) {  
        super.setName("customRealm");  
    }  

    @Autowired  
    private AdminUserService adminUserService;  

    /** 
     * 認證 
     */  
    @Override  
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {  

        // token中包含使用者輸入的使用者名稱和密碼  
        // 第一步從token中取出使用者名稱  
        String userName = (String) token.getPrincipal();  
        // 第二步:根據使用者輸入的userCode從資料庫查詢  
        TAdminUser adminUser = adminUserService.getAdminUserByUserName(userName);  
        // 如果查詢不到返回null  
        if (adminUser == null) {//  
            return null;  
        }  
        // 獲取資料庫中的密碼  
        String password = adminUser.getPassword();  
        /** 
         * 認證的使用者,正確的密碼 
         */  
        AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(adminUser, password, this.getName());  
               //MD5 加密+加鹽+多次加密  
//<span style="color:#ff0000;">SimpleAuthenticationInfo authcInfo = new SimpleAuthenticationInfo(adminUser, password,ByteSource.Util.bytes(salt), this.getName());</span>  
        return authcInfo;  
    }  

    /** 
     * 授權,只有成功通過<span style="font-family: Arial, Helvetica, sans-serif;">doGetAuthenticationInfo方法的認證後才會執行。</span> 
     */  
    @Override  
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {  
        // 從 principals獲取主身份資訊  
        // 將getPrimaryPrincipal方法返回值轉為真實身份型別(在上邊的doGetAuthenticationInfo認證通過填充到SimpleAuthenticationInfo中身份型別),  
        TAdminUser activeUser = (TAdminUser) principals.getPrimaryPrincipal();  
        // 根據身份資訊獲取許可權資訊  
        // 從資料庫獲取到許可權資料  
        TAdminRole adminRoles = adminUserService.getAdminRoles(activeUser);  
        // 單獨定一個集合物件  
        List<String> permissions = new ArrayList<String>();  
        if (adminRoles != null) {  
            permissions.add(adminRoles.getRoleKey());  
        }  
        // 查到許可權資料,返回授權資訊(要包括 上邊的permissions)  
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();  
        // 將上邊查詢到授權資訊填充到simpleAuthorizationInfo物件中  
        simpleAuthorizationInfo.addStringPermissions(permissions);  
        return simpleAuthorizationInfo;  
    }  

    // 清除快取  
    public void clearCached() {  
        PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();  
        super.clearCache(principals);  
    }  
}  

5 快取配置

ehcache.xml程式碼如下:

[java] view plain copy print?
  1. <ehcache updateCheck=“false” name=“shiroCache”>    
  2.     <defaultCache    
  3.             maxElementsInMemory=”10000”
  4.             eternal=”false”
  5.             timeToIdleSeconds=”120”
  6.             timeToLiveSeconds=”120”
  7.             overflowToDisk=”false”
  8.             diskPersistent=”false”
  9.             diskExpiryThreadIntervalSeconds=”120”
  10.             />    
  11. </ehcache>   
<ehcache updateCheck="false" name="shiroCache">  
    <defaultCache  
            maxElementsInMemory="10000"  
            eternal="false"  
            timeToIdleSeconds="120"  
            timeToLiveSeconds="120"  
            overflowToDisk="false"  
            diskPersistent="false"  
            diskExpiryThreadIntervalSeconds="120"  
            />  
</ehcache> 
通過使用ehache中就避免第次都向伺服器傳送許可權授權(doGetAuthorizationInfo)的請求。

6.自定義表單編碼過濾器

CustomFormAuthenticationFilter程式碼,認證之前呼叫,可用於驗證碼校驗

[java] view plain copy print?
  1. publicclass CustomFormAuthenticationFilter extends FormAuthenticationFilter {    
  2.     // 原FormAuthenticationFilter的認證方法  
  3.     @Override
  4.     protectedboolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {    
  5.         // 在這裡進行驗證碼的校驗  
  6.         // 從session獲取正確驗證碼  
  7.         HttpServletRequest httpServletRequest = (HttpServletRequest) request;    
  8.         HttpSession session = httpServletRequest.getSession();    
  9.         // 取出session的驗證碼(正確的驗證碼)  
  10.         String validateCode = (String) session.getAttribute(”validateCode”);    
  11.         // 取出頁面的驗證碼  
  12.         // 輸入的驗證和session中的驗證進行對比  
  13.         String randomcode = httpServletRequest.getParameter(”randomcode”);    
  14.         if (randomcode != null && validateCode != null && !randomcode.equals(validateCode)) {    
  15.             // 如果校驗失敗,將驗證碼錯誤失敗資訊,通過shiroLoginFailure設定到request中  
  16.             httpServletRequest.setAttribute(”shiroLoginFailure”“randomCodeError”);    
  17.             // 拒絕訪問,不再校驗賬號和密碼  
  18.             returntrue;    
  19.         }    
  20.         returnsuper.onAccessDenied(request, response);    
  21.     }    
  22. }    
public class CustomFormAuthenticationFilter extends FormAuthenticationFilter {  
    // 原FormAuthenticationFilter的認證方法  
    @Override  
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {  
        // 在這裡進行驗證碼的校驗  

        // 從session獲取正確驗證碼  
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;  
        HttpSession session = httpServletRequest.getSession();  
        // 取出session的驗證碼(正確的驗證碼)  
        String validateCode = (String) session.getAttribute("validateCode");  

        // 取出頁面的驗證碼  
        // 輸入的驗證和session中的驗證進行對比  
        String randomcode = httpServletRequest.getParameter("randomcode");  
        if (randomcode != null && validateCode != null && !randomcode.equals(validateCode)) {  
            // 如果校驗失敗,將驗證碼錯誤失敗資訊,通過shiroLoginFailure設定到request中  
            httpServletRequest.setAttribute("shiroLoginFailure", "randomCodeError");  
            // 拒絕訪問,不再校驗賬號和密碼  
            return true;  
        }  
        return super.onAccessDenied(request, response);  
    }  
}  

在此符上驗證碼jsp介面的程式碼  validatecode.jsp

[html] view plain copy print?
  1. <%@ page language=“java”contentType=“text/html; charset=UTF-8”
  2.     pageEncoding=“UTF-8”%>
  3. <%@ page import=“java.util.Random”%>
  4. <%@ page import=“java.io.OutputStream”%>
  5. <%@ page import=“java.awt.Color”%>
  6. <%@ page import=“java.awt.Font”%>
  7. <%@ page import=“java.awt.Graphics”%>
  8. <%@ page import=“java.awt.image.BufferedImage”%>
  9. <%@ page import=“javax.imageio.ImageIO”%>
  10. <%    
  11.     int width = 60;    
  12.     int height = 32;    
  13.     //create the image    
  14.     BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);    
  15.     Graphics g = image.getGraphics();    
  16.     // set the background color    
  17.     g.setColor(new Color(0xDCDCDC));    
  18.     g.fillRect(0, 0, width, height);    
  19.     // draw the border    
  20.     g.setColor(Color.black);    
  21.     g.drawRect(0, 0, width - 1, height - 1);    
  22.     // create a random instance to generate the codes    
  23.     Random rdm = new Random();    
  24.     String hash1 = Integer.toHexString(rdm.nextInt());    
  25.     // make some confusion    
  26.     for (int i = 0; i <50; i++) {    
  27.         int x = rdm.nextInt(width);    
  28.         int y = rdm.nextInt(height);    
  29.         g.drawOval(x, y, 0, 0);    
  30.     }    
  31.     // generate a random code    
  32.     String capstr = hash1.substring(0, 4);    
  33.     //將生成的驗證碼存入session    
  34.     session.setAttribute(“validateCode”, capstr);    
  35.     g.setColor(new Color(0, 100, 0));    
  36.     g.setFont(new Font(“Candara”, Font.BOLD, 24));    
  37.     g.drawString(capstr, 8, 24);    
  38.     g.dispose();    
  39.     //輸出圖片    
  40.     response.setContentType(“image/jpeg”);    
  41.     out.clear();    
  42.     out = pageContext.pushBody();    
  43.     OutputStream strm = response.getOutputStream();    
  44.     ImageIO.write(image, “jpeg”, strm);    
  45.     strm.close();    
  46. %>
<%@ page language="java" contentType="text/html; charset=UTF-8"  
    pageEncoding="UTF-8"%>  
<%@ page import="java.util.Random"%>  
<%@ page import="java.io.OutputStream"%>  
<%@ page import="java.awt.Color"%>  
<%@ page import="java.awt.Font"%>  
<%@ page import="java.awt.Graphics"%>  
<%@ page import="java.awt.image.BufferedImage"%>  
<%@ page import="javax.imageio.ImageIO"%>  
<%  
    int width = 60;  
    int height = 32;  
    //create the image  
    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);  
    Graphics g = image.getGraphics();  
    // set the background color  
    g.setColor(new Color(0xDCDCDC));  
    g.fillRect(0, 0, width, height);  
    // draw the border  
    g.setColor(Color.black);  
    g.drawRect(0, 0, width - 1, height - 1);  
    // create a random instance to generate the codes  
    Random rdm = new Random();  
    String hash1 = Integer.toHexString(rdm.nextInt());  
    // make some confusion  
    for (int i = 0; i < 50; i++) {  
        int x = rdm.nextInt(width);  
        int y = rdm.nextInt(height);  
        g.drawOval(x, y, 0, 0);  
    }  
    // generate a random code  
    String capstr = hash1.substring(0, 4);  
    //將生成的驗證碼存入session  
    session.setAttribute("validateCode", capstr);  
    g.setColor(new Color(0, 100, 0));  
    g.setFont(new Font("Candara", Font.BOLD, 24));  
    g.drawString(capstr, 8, 24);  
    g.dispose();  
    //輸出圖片  
    response.setContentType("image/jpeg");  
    out.clear();  
    out = pageContext.pushBody();  
    OutputStream strm = response.getOutputStream();  
    ImageIO.write(image, "jpeg", strm);  
    strm.close();  
%>  
7.登入控制器方法 [java] view plain copy print?
  1. /**  
  2.  * 到登入介面  
  3.  *   
  4.  * @return  
  5.  * @throws Exception  
  6.  */
  7. @RequestMapping(“login.do”)    
  8. public String adminPage(HttpServletRequest request) throws Exception {    
  9.     // 如果登陸失敗從request中獲取認證異常資訊,shiroLoginFailure就是shiro異常類的全限定名  
  10.     String exceptionClassName = (String) request.getAttribute(”shiroLoginFailure”);    
  11.     // 根據shiro返回的異常類路徑判斷,丟擲指定異常資訊  
  12.     if (exceptionClassName != null) {    
  13.         if (UnknownAccountException.class.getName().equals(exceptionClassName)) {    
  14.             // 最終會拋給異常處理器  
  15.             thrownew CustomJsonException(“賬號不存在”);    
  16.         } elseif (IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {    
  17.             thrownew CustomJsonException(“使用者名稱/密碼錯誤”);    
  18.         } elseif (“randomCodeError”.equals(exceptionClassName)) {    
  19.             thrownew CustomJsonException(“驗證碼錯誤 ”);    
  20.         } else {    
  21.             thrownew Exception();// 最終在異常處理器生成未知錯誤  
  22.         }    
  23.     }    
  24.     // 此方法不處理登陸成功(認證成功),shiro認證成功會自動跳轉到上一個請求路徑  
  25.     // 登陸失敗還到login頁面  
  26.     return“admin/login”;    
  27. }    
/** 
 * 到登入介面 
 *  
 * @return 
 * @throws Exception 
 */  
@RequestMapping("login.do")  
public String adminPage(HttpServletRequest request) throws Exception {  
    // 如果登陸失敗從request中獲取認證異常資訊,shiroLoginFailure就是shiro異常類的全限定名  
    String exceptionClassName = (String) request.getAttribute("shiroLoginFailure");  
    // 根據shiro返回的異常類路徑判斷,丟擲指定異常資訊  
    if (exceptionClassName != null) {  
        if (UnknownAccountException.class.getName().equals(exceptionClassName)) {  
            // 最終會拋給異常處理器  
            throw new CustomJsonException("賬號不存在");  
        } else if (IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {  
            throw new CustomJsonException("使用者名稱/密碼錯誤");  
        } else if ("randomCodeError".equals(exceptionClassName)) {  
            throw new CustomJsonException("驗證碼錯誤 ");  
        } else {  
            throw new Exception();// 最終在異常處理器生成未知錯誤  
        }  
    }  
    // 此方法不處理登陸成功(認證成功),shiro認證成功會自動跳轉到上一個請求路徑  
    // 登陸失敗還到login頁面  
    return "admin/login";  
}  

8.使用者回顯Controller

當用戶登入認證成功後,CustomRealm在呼叫完doGetAuthenticationInfo時,通過

[java] view plain copy print?
  1. AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(adminUser, password, this.getName());    
  2.     return authcInfo;   
AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(adminUser, password, this.getName());  
    return authcInfo; 
SimpleAuthenticationInfo構造引數的第一個引數傳入一個使用者的物件,之後,可通過Subject subject = SecurityUtils.getSubject();中的subject.getPrincipal()獲取到此物件。所以需要回顯使用者資訊時,我這樣呼叫的 [java] view plain copy print?
  1. @RequestMapping(“index.do”)    
  2. public String index(Model model) {    
  3.     //從shiro的session中取activeUser  
  4.     Subject subject = SecurityUtils.getSubject();    
  5.     //取身份資訊  
  6.     TAdminUser adminUser =  (TAdminUser) subject.getPrincipal();    
  7.     //通過model傳到頁面  
  8.     model.addAttribute(”adminUser”, adminUser);    
  9.     return“admin/index”;    
  10. }    
@RequestMapping("index.do")  
public String index(Model model) {  
    //從shiro的session中取activeUser  
    Subject subject = SecurityUtils.getSubject();  
    //取身份資訊  
    TAdminUser adminUser =  (TAdminUser) subject.getPrincipal();  
    //通過model傳到頁面  
    model.addAttribute("adminUser", adminUser);  
    return "admin/index";  
}  

9.在jsp頁面中控制權限

先引入shiro的標頭檔案

[html] view plain copy print?
  1. <!– shiro頭引入 –>
  2. <%@ taglib uri=“http://shiro.apache.org/tags”prefix=“shiro”%>
<!-- shiro頭引入 -->  
<%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro"%>  
採用shiro標籤對許可權進行處理