shiro基本配置和使用


這里講shiro整合spring 實現登錄驗證 和權限攔截

首先pom文件添加依賴

<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.3.2</version>
</dependency>

<!-- spring整合shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>


<!-- ehcache-->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.11</version>
</dependency>

shiro要結合ehcache這個緩存框架 可以實現一些功能 比如限制用戶登錄密碼錯誤次數 然后限制多久時間內,限制登錄

接下來就來就是配置文件 首先web.xml
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>DelegatingFilterProxy</param-name>
<param-value>true</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

這是配置一個shiro過濾器 將所有的請求都交給shiro處理 至於spring的配置我這里就不寫了 和正常的配置一樣

然后ehcache緩存框架需要一個配置文件 我這里貼出來 文件名就叫 ehcache.xml
 1 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">  
 2 
 3        <diskStore path="${webapp.root}"/>  
 4      
 5     <defaultCache
 6             maxElementsInMemory="10000"
 7             maxElementsOnDisk="0"
 8             eternal="true"
 9             overflowToDisk="true"
10             diskPersistent="false"
11             timeToIdleSeconds="0"
12             timeToLiveSeconds="0"
13             diskSpoolBufferSizeMB="50"
14             diskExpiryThreadIntervalSeconds="120"
15             memoryStoreEvictionPolicy="LFU"
16     />
17    </ehcache>
接下來就是spring整合shiro的配置文件
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 5 
 6 
 7 <!-- 配置ehCache緩存支持-->
 8 <bean name="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
 9 <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"></property>
10 </bean>
11 
12 
13     <!-- 自定義Realm-->
14 <bean name="userRealm" class="com.newer.web.shiro.MyRealm" >
15 
16     <!--注入加密算法類 -->
17     <property name="credentialsMatcher">
18 
19     <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
20         <!--加密算法名 -->
21         <property name="hashAlgorithmName" value="MD5"/>
22         <!--加密次數 -->
23         <property name="hashIterations" value="6"/>
24     </bean>
25 
26     </property>
27 
28 
29 </bean>
30 
31 
32 <!-- shiro安全管理器-->
33 <bean name="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
34 <property name="cacheManager" ref="cacheManager"></property>
35 <property name="realm" ref="userRealm"></property>
36 </bean>
37 
38 
39 <!-- 管理shiro bean的生命周期 -->
40 <bean name="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"></bean>
41 
42 
47 
48     <!--shiro核心過濾器配置-->
49     <bean name="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
50         <property name="securityManager" ref="securityManager"/>
51         <property name="loginUrl" value="/login.jsp"></property> <!-- 沒有認證  跳轉的登錄連接 -->
52         <property name="unauthorizedUrl" value="/unauthorized.jsp"></property> <!-- 沒有訪問權限 跳轉的頁面 -->

82 <!--這里使用 從數據庫查詢出來要攔截的url集合 注入到這個對象中 實現攔截 --> 83 <property name="filterChainDefinitionMap" ref="map"/> 86 </bean> 87 88 89 <!--實例工廠方法 將執行shiroFilterUtils類的build的方法 --> 90 <bean name="map" factory-bean="shiroFilterUtils" factory-method="build"/> 91 92 <!--這個類將從數據庫中查詢要攔截的url信息--> 93 <bean name="shiroFilterUtils" class="com.newer.util.ShiroFilterUtils"/> 97 </beans>

 

別的配置不說  shiro核心過濾器bean的 name的值 一定要與web.xml里面配置的shiro過濾器的名字一樣 否則會報錯

然后我這里是使用實例工廠方法  將一個存有要攔截的url的map集合 注入到ShiroFilterFactoryBean 中的filterChainDefinitionMap屬性

這樣當我們的請求經過shiro過濾器時  會根據我們配置的要攔截的url和使用相應的攔截器 對請求進行處理  

現在把我這個工具類貼出來

/**
 * 這個類會在 spring容器初始化bean時  從數據庫將要攔截的url
 * 查詢出來 封裝成集合  注入到ShiroFilterFactoryBean類的filterChainDefinitions屬性中
 * 這樣實現對需要相應權限才能訪問的url進行攔截 並由shiro驗證是否具有相應權限
 */

public class ShiroFilterUtils {

  public Map<String,String> build(){

   

     Map<String,String> map= new LinkedHashMap<String, String>();

//添加固定要攔截的url map.put("/user/login.do","anon"); map.put("/login.jsp","anon"); map.put("/**","authc"); return map; } }

這里講一下  url和攔截器的語法

url使用的是 Ant風格

 ? 匹配任何單字符

 * 匹配0或者任意數量的字符

** 匹配0或者更多的目錄

攔截器常用有:
anon 匿名的 不需要認證 也可以訪問
authc 必須認證才可以訪問 沒有認證會跳轉登錄鏈接
user 登錄之后啟用了記住我功能 就可以訪問

roles 例如 roles[管理員] 表示必須具有管理員權限才可操作 如果是roles[管理員,經理] 表示要具有管理員和經理權限才可以訪問
------------------------------------------
shiro會將請求的url按照順序和map集合中的所有url匹配 如果匹配到了 不會再匹配后續url 所以要注意 map集合中要攔截的url的順序
我這里就沒有將要攔截的url 從數據庫中查出 如果需要從數據集中查出 然后將要攔截的url作為key 要使用的攔截器作為value 存入這個map集合即可


權限管理就這么多 接下來說登錄認證 貼出我的controller
@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/login")
    public String login(String userName, String userPassword, ModelMap map){

        //得到當前 Subject
        Subject currentSubject= SecurityUtils.getSubject();

            //創建用戶名密碼 token
            UsernamePasswordToken token= new UsernamePasswordToken(userName,userPassword);

            //記住當前用戶 關掉瀏覽器 重開也能訪問 不是authc 攔截器的url
            token.setRememberMe(true);

            try {
                //執行登錄方法
            currentSubject.login(token);

            }catch (IncorrectCredentialsException ie){
                //將拋出的登錄異常 存儲 然后返回登錄頁面 顯示給用戶
                map.put("loginMessage","用戶名或密碼錯誤!!!");
                return "forward:/login.jsp";

            }catch (AuthenticationException ae){ //所有異常的父類
              map.put("loginMessage","未知錯誤 請聯系管理員");
              return "forward:/login.jsp";
            }


        return "success";
    }


    @RequestMapping("/logout")
    public String logout(){

        //得到當前 Subject
        Subject currentSubject= SecurityUtils.getSubject();

        //注銷當前 Subject
        currentSubject.logout();

      return "redirect:/login.jsp";

    }






   //這里面沒有去寫注冊方法了  注冊的時候 要將密碼 通過這樣加密后存入到數據庫
    public static void main(String[] args) {

        //生成MD5加密的密碼  參1:加密方式 ,參2:未加密的密碼  參3:鹽值 使用當前用戶名  參4:加密次數
        Object str= new SimpleHash("MD5","123456","zhangsan",6);

        System.out.println("str = " + str);
    }


}

 


當執行
login()方法時 會調用我們在shiro配置文件中配置的自定義Realm類 login方法出現錯誤 會拋出異常 我們用catch可以捕獲對應異常

接下來貼出我的
Realm類
@Component
public class MyRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    @Autowired
    private AuthorityService authorityService;



    @Override    //認證方法
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        //將token強轉成 用戶密碼token
        UsernamePasswordToken token=(UsernamePasswordToken)authenticationToken;

        //根據傳入的用戶名 查詢數據庫  返回用戶對象
        User user=userService.queryByUserName(token.getUsername());

        //沒有查到用戶 直接拋出異常
        if(user==null){

            throw  new IncorrectCredentialsException();

        }

        //根據當前用戶名 生成鹽值  用於結合加密算法對密碼進行加密
        ByteSource salt=ByteSource.Util.bytes(token.getUsername());

        //將用戶名和密碼 交由shiro認證 如果出錯會拋出對應異常   參數1:用戶名 參數2:用戶密碼 參3:鹽值 參數4:當前Realm的名字
        return new SimpleAuthenticationInfo(user.getUserName(),user.getUserPassword(),salt,this.getName());

    }



    @Override   //授權方法
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        //獲得用戶名
        String userName= (String) principalCollection.getPrimaryPrincipal();

        //根據用戶名 查詢當前用戶 擁有的權限
        Set<String>  roles=authorityService.queryByUserName(userName);

        //將當前權限集合 返回交給shiro處理 權限認證
        return new  SimpleAuthorizationInfo(roles);
    }





}

 

第二個授權方法  就是當請求需要對應權限的攔截器的url時   shiro會調用這個方法  然后我們根據當前用戶名 查詢出當前用戶所擁有的權限

然后交給shiro 由他去比對當前用戶是否擁有可以訪問的資格 如果沒有就會跳轉到我們在配置文件中 shiro過濾器配置的unauthorizedUrl屬性的值去

 

shiro的基本用法就這些  網上看了很多教程 都是各不相同  不像別的框架  教程都差不多  暫時總結到這里 后續有新的用法 再來加上吧 




 

 

 

 

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM