1. 程式人生 > >springboot2.0整合shiro攻略

springboot2.0整合shiro攻略

Shiro是什麼

這裡寫圖片描述
Apache Shiro是一個強大且易用的Java安全框架,執行身份驗證、授權、密碼學和會話管理。使用Shiro的易於理解的API,您可以快速、輕鬆地獲得任何應用程式,從最小的移動應用程式到最大的網路和企業應用程式。簡單的講,Shiro是一個Java平臺的開源許可權框架,用於認證和訪問授權。

Shiro三個核心元件

Subject, SecurityManager 和 Realms

  • Subject:即“當前操作使用者”。但是,在Shiro中,Subject這一概念並不僅僅指人,也可以是第三方程序、後臺帳戶(Daemon Account)或其他類似事物。它僅僅意味著“當前跟軟體互動的東西”。但考慮到大多數目的和用途,你可以把它認為是Shiro的“使用者”概念。Subject代表了當前使用者的安全操作,SecurityManager則管理所有使用者的安全操作。
  • SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通過SecurityManager來管理內部元件例項,並通過它來提供安全管理的各種服務。
  • Realm: Realm充當了Shiro與應用安全資料間的“橋樑”或者“聯結器”。也就是說,當對使用者執行認證(登入)和授權(訪問控制)驗證時,Shiro會從應用配置的Realm中查詢使用者及其許可權資訊。

      從這個意義上講,Realm實質上是一個安全相關的DAO:它封裝了資料來源的連線細節,並在需要時將相關資料提供給Shiro。當配置Shiro時,你必須至少指定一個Realm,用於認證和(或)授權。配置多個Realm是可以的,但是至少需要一個。
      
      Shiro內建了可以連線大量安全資料來源(又名目錄)的Realm,如LDAP、關係資料庫(JDBC)、類似INI的文字配置資源以及屬性檔案等。如果預設的Realm不能滿足需求,你還可以插入代表自定義資料來源的自己的Realm實現。
    Shrio

Shrio授權原型

授權三要素:使用者,角色,許可權(僅僅是操作許可權,資料許可權必須與業務需求緊密結合),資源(url)。

簡單的講:使用者分配角色,角色定義許可權。訪問授權時支援角色或者許可權,並且支援多級的許可權定義。

Q:對組的支援?
A:shiro預設不支援對組設定許可權。

Q:是否可以滿足對組進行角色分配的需求?
A:擴充套件Realm,可以支援對組進行分配角色,其實就是給該組下的所有使用者分配許可權。

Q:對資料許可權的支援? 在業務系統中定義?
A:shiro僅僅實現對操作許可權的控制,用於在前端控制元素隱藏或者顯示,以及對資源訪問許可權進行檢查。資料許可權與具體的業務需求緊密關聯,shiro本身無法實現對資料許可權的控制。

Q:動態許可權分配?
A:擴充套件org.apache.shiro.realm.Realm,支援動態許可權分配。

Q:與Spring整合?
A:shiro-spring專案可以與Spring無縫整合,shiro還支援jsp標籤等。

shiro內建過濾器

簡單的說只要理解這幾個就夠了
這裡寫圖片描述

下面是比較詳細的解釋
這裡寫圖片描述
- org.apache.shiro.web.filter.authc.AnonymousFilter
例如/admins/**=anon 沒有引數,表示可以匿名使用。
- org.apache.shiro.web.filter.authc.FormAuthenticationFilter
例如/admins/user/**=authc表示需要認證才能使用,沒有引數
- org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
例如/admins/user/**=authcBasic沒有引數表示httpBasic認證
- org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
例如/admins/user/=perms[user:add:],perms引數可以寫多個,多個時必須加上引號,並且引數之間用逗號分割,例如/admins/user/=perms[“user:add:,user:modify:*”],當有多個引數時必須每個引數都通過才通過,想當於
isPermitedAll()方法。
- org.apache.shiro.web.filter.authz.PortFilter
例如/admins/user/**=port[8081],當請求的url的埠不是8081是跳轉到schemal://serverName:8081?queryString,其中schmal是協議http或https等,serverName是你訪問的host,8081是url配置裡port的埠,queryString
是你訪問的url裡的?後面的引數。
- org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter,
例如/admins/user/=rest[user],根據請求的方法,相當於/admins/user/=perms[user:method] ,其中method為post,get,delete等。
- org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
例如/admins/user/=roles[admin],引數可以寫多個,多個時必須加上引號,並且引數之間用逗號分割,當有多個引數時,例如/admins/user/=roles[“admin,guest”],每個引數通過才算通過,相當於hasAllRoles()方法。
- org.apache.shiro.web.filter.authz.SslFilter
例如/admins/user/**=ssl沒有引數,表示安全的url請求,協議為https
user:例如/admins/user/**=user沒有引數表示必須存在使用者,當登入操作時不做檢查
- org.apache.shiro.web.filter.authc.UserFilter
例如/admins/user/**=user沒有引數表示必須存在使用者,當登入操作時不做檢查

可以理解為,過濾器分為兩組,一組是認證過濾器anon,authcBasic,auchc,user,一組是授權過濾器perms,roles,ssl,rest,port。

可能遇到的坑

  • java.lang.NoClassDefFoundError: org/apache/shiro/mgt/SecurityManager
    用maven重新整理專案,並且重新build clean compile。

  • Bean named ‘&shiroFilter’ is expected to be of type ‘org.springframework.beans.factory.config.BeanPostProcessor’ but was actually of type ‘org.springframework.beans.factory.support.NullBean’
    出現這種情況一般是ShiroFilterFactoryBean的方法返回了null導致。

springboot2-shiro實戰部分

maven引入

        <!-- shiro-spring許可權管理 -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>

springboot2的shiro配置

import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Shiro配置類
 * 1.配置ShiroFilterFactory 2.配置SecurityManager
 * @author zhengkai
 *
 */
@Configuration
public class ShiroConfig {
    /**
     * 配置shiro過濾器
     * @author zhengkai
     */
    @Bean("shiroFilter")                                                                                                                                                                                                               
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        //1.定義shiroFactoryBean
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
        //2.設定securityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //3.LinkedHashMap是有序的,進行順序攔截器配置
        Map<String,String> filterChainMap = new LinkedHashMap<String,String>();
        //4.配置logout過濾器
        filterChainMap.put("/logout", "logout");
        //5.所有url必須通過認證才可以訪問
        filterChainMap.put("/**","authc");
        //6.設定預設登入的url
        shiroFilterFactoryBean.setLoginUrl("/login");
        //7.設定成功之後要跳轉的連結
        shiroFilterFactoryBean.setSuccessUrl("/index");
        //8.設定未授權介面
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        //9.設定shiroFilterFactoryBean的FilterChainDefinitionMap
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
        return shiroFilterFactoryBean;
    }
    /**
     * 配置安全管理器   
     * @author zhengkai
     */
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        return securityManager;
    }

}

這裡寫圖片描述
啟動spring之後,發現shiroFilter的話。就證明成功了。