Shiro快速入門


1.什么是Shiro

Shiro是Java的一個安全框架, 完成權限控制的任務.

權限控制的基本功能: 認證(讓系統知道你是誰); 授權(讓系統知道你能做什么)
權限控制常用的技術: 過濾器/攔截器, 或者使用代理模式
權限控制的數據模型: 權限表-(多對多)-角色表-(多對多)-用戶表

shiri的組成

 

shiro的調用流程

Application code:應用程序代碼
Subject:當前用戶
SecurityManager:安全管理器,shiro框架的核心對象,管理各個組件
Realm:獲取權限信息, 決定subject的訪問權限, 可以有多個

 

2.Shiro的使用

2.1登錄

Subject subject = SecurityUtils.getSubject();  
UsernamePasswordToken token = new UsernamePasswordToken(username, password); 
try{
    // 注意:登錄不成功以拋異常的方式通知
    subject.login(token);   
}catch (UnknownAccountException e) {
    // 沒找到用戶名
}catch (IncorrectCredentialsException e) {
    // 用戶名密碼不匹配
}catch (AuthenticationException e) {
    // 其他登錄錯誤
}
if (subject.isAuthenticated()) {
    // 登錄成功后, 取回認證時通過簽名存儲的對象
    User user = (User) subject.getPrincipal();
}

 

2.2 在realm里管理用戶~權限

public class MyRealm extends AuthorizingRealm {
    
  // 登錄及認證 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { // 獲得登錄用的token UsernamePasswordToken token = (UsernamePasswordToken) token; // 獲得封裝的username String username = token.getUsername(); User user = userDao.findByUsername(username); if (null == user) { return null; } else { // 獲得真正的password String password = user.getPassword(); // 創建簡單認證對象, 返回給安全管理器 // 參數一:可放入任何對象的簽名, 執行subject.login()方法后可從subject.getPrincipal()取回 // 參數二:封裝真正的密碼, 交由安全管理器比對 // 參數三:當前realm的名稱 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, this.getClass().getSimpleName()); return info; } } // 授權 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 獲得簽名, 可做進一步查詢 User user = (User) principals.getPrimaryPrincipal(); // 創建簡單授權對象 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //授予perms["keyword"] info.addStringPermission("staff"); //授予role["keyword"] info.addRole("staff"); return info; } }

 

2.3 配置及管理訪問目標~權限

2.3.1 過濾器方式:

web.xml

  <!-- shiro過濾器, 從spring工廠拿, beanname為"shiroFilter" -->
  <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>/*</url-pattern>
  </filter-mapping>

applicationContext.xml

  <!-- shiro: 自定義的realm -->
    <bean id = "userDefineRealm" class="com.zx.bos.shiro.UserDefineRealm"></bean>
    
    <!-- 二級緩存-->
    <bean id="ehCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"></property>
    </bean>
    
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!-- realm需注冊給安全管理器 -->
        <property name="realm" ref = "userDefineRealm"></property>
        <!-- 使用ehcache二級緩存, 沒必要頻繁查詢權限 -->
        <property name="cacheManager" ref="ehCacheManager"></property>
    </bean>
    
    
    <!-- shiro使用方式1, 對URL進行控制  -->
    <bean id = "shiroFilter" class = "org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- 注入安全管理器 -->
        <property name="securityManager" ref="securityManager"></property>
        <!-- 未登錄時跳轉到登錄頁面 -->
        <property name="loginUrl" value="/login.jsp"/>
        <!-- 登錄成功頁面 -->
        <property name="successUrl" value="/index.jsp"/>   <!-- 登錄后跳轉到登陸前被攔截的頁面, 不跳轉至此 -->
        <!-- 權限不足提示頁面 -->
        <property name="unauthorizedUrl" value="/unauthorizedUrl.jsp"/>
        <!-- URL攔截規則 -->  <!-- 有先后順序 從上往下匹配 -->
        <property name="filterChainDefinitions">
            <value>
                /css/** = anon
                /images/** = anon
                /js/** = anon
                /login.jsp* = anon   <!-- 后面帶參數 -->
                /validatecode.jsp* = anon
          /page_base_staff.action = roles["staff"] /userAction_login.action = anon
/* = authc </value> </property> </bean>

anon:可以匿名使用。
authc:需要認證(登錄)才能使用
roles:可以帶參數, 參數可以多個,例如roles["admin,guest"], 表示每個參數都通過才算通過
perms:可以帶參數, 參數可以多個,perms["user:add:*,user:modify:*"]
port:port[8081]表示當請求的url的端口不是8081時跳轉到schema://serverName:8081?queryParams
user:必須存在用戶,登錄操作時不做檢查

 

2.3.2 注解方式:

    <!-- shiro使用方式2, 使用注解對方法進行控制. 不同於url方式權限不足時跳轉界面,它直接拋出異常 -->
    <!-- 代理 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
        <property name="proxyTargetClass" value="true"></property>   <!-- 使用cglib創建代理對象,  默認false用jdk動態代理 -->
    </bean>
    <!-- 切面類 -->
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>  
    </bean>

注意捕獲權限不足時拋出的異常. 如果在struts里需要配置

struts.xml

<global-results>
    <result name="unauthorizedUrl">/unauthorizedUrl.jsp</result>
</global-results>
<!-- 接收異常 -->
<global-exception-mappings>
    <exception-mapping result="unauthorizedUrl" exception="org.apache.shiro.authz.AuthorizationException"></exception-mapping>
</global-exception-mappings>
例如:
@RequiresRoles("rolename");
void someMethod();
@RequiresPermissions({"file:read", "write:aFile.txt"});
void someMethod();
最后說一遍, 需要處理可能的AuthorizationException異常
 
注解方式是在方法級別的控制,無法做類級別的控制訪問。
過濾器方式是根據訪問的URL進行控制。允許使用*通配URL,所以可以進行粗粒度,也可以進行細粒度控制。
 

2.4 在JSP頁面使用shiro標簽

使用shiro標簽, 根據權限過濾部分內容
 
<shiro:authenticated>      登錄之后
<shiro:notAuthenticated> 沒有登錄
<shiro:hasRole name="abc">     擁有角色abc
<shiro:lacksRole name="abc">   沒有角色abc
<shiro:hasPermission name="abc">    擁有權限資源abc
<shiro:lacksPermission name="abc">  沒有abc權限資源
<shiro:principal>   取回簽名對象


免責聲明!

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



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