Shiro安全框架簡介以及身份驗證
一、Shiro簡介
官網 http://shiro.apache.org/download.html
Apache Shiro是一個強大且易用的Java安全框架,執行身份驗證、授權、密碼學和會話管理。使用Shiro的易於理解的API,您可以快速、輕松地獲得任何應用程序,從最小的移動應用程序到最大的網絡和企業應用程序。
三個核心組件: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實現。 ------來源百度百科 二、項目配置
1.創建一個Maven項目
2.下載shirojar包,因為是Maven管理的 所以添加下依賴,就從中央倉庫將jar包下載到本地倉庫了
<dependencies> <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.2.4</version> </dependency> </dependencies>
這個我下的是1.2.4版本,最新版本1.4.0,不支持IniSecurityManagerFactory解析ini,顯示構造函數過時 如下圖
有個slf4j api 包,這個是一個api接口包,我們還要引入slf4j的實現包,否則會報警告
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.21</version> <scope>test</scope> </dependency>
<scope>標簽要刪除 否則會報如下錯誤
3.在src/main/resources/目錄下新建個shiro配置文件File,shiro.ini
建好後會彈出個記事本,關閉,不用記事本打開,右鍵選中openwith選TextEditor
[users] //用戶
Robin=123456 //用戶名=密碼
Tom=123
4.在src/main/resources/目錄下加個log4j.properties日誌文件
5.在src/main/java目錄下建個包com.guo.shiro,包下新建個類HelloWorld.java
import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.Factory; public class HelloWorld { public static void main(String[] args) { // 讀取配置文件,初始化SecurityManager工廠 Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro.ini"); // 獲取securityManager實例 SecurityManager securityManager=factory.getInstance(); // 把securityManager實例綁定到SecurityUtils SecurityUtils.setSecurityManager(securityManager); // 得到當前執行的用戶 Subject currentUser=SecurityUtils.getSubject(); // 創建token令牌,用戶名/密碼 UsernamePasswordToken token=new UsernamePasswordToken("Robin", "123456"); try{ // 身份認證 currentUser.login(token); System.out.println("身份認證成功!"); }catch(AuthenticationException e){ e.printStackTrace(); System.out.println("身份認證失敗!"); } // 退出 currentUser.logout(); } }
這個身份驗證獲取的用戶名和密碼 是配置文件shiro.ini中的,要獲取和驗證數據庫中的用戶名和密碼,往下看
三、身份認證
1、Subject 認證主體
Subject 認證主體包含兩個信息: Principals:身份,可以是用戶名,郵件,手機號碼等,用來標識一個登錄主體身份; Credentials:憑證,常見有密碼,數字證書等等;
2、身份認證流程
Subject認證主體調用login()方法,傳給SecurityManager處理,SecurityManager裏有個
Authenticator實例,有個AuthenticatoStrategy策略,要讀取安全數據的話
涉及到Realm 來獲取安全數據
3、Realm
Realm:意思是域,Shiro 從 Realm 中獲取驗證數據; Realm 有很多種類,例如常見的 jdbcrealm,jndirealm,text realm。
4.以JDBCReaml 為例
a、 新建個db_shiro 庫,建個users表,添加用戶名Robin,密碼123456
b、在mvnrepori 查找C3P0 依賴代碼 和commons-logging 阿帕奇的公共日誌 依賴代碼
還有mysql的驅動包 依賴代碼 貼入pom
<!-- https://mvnrepository.com/artifact/c3p0/c3p0 --> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging --> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency>
c、新建個jdbc_reaml.ini配置JDBCReaml
[main]
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
dataSource.driverClass=com.mysql.jdbc.Driver
dataSource.jdbcUrl=jdbc:mysql://localhost:3306/db_shiro
dataSource.user=root
dataSource.password=123456
jdbcRealm.dataSource=$dataSource
securityManager.realms=$jdbcRealm
dataSource=com.mchange.v2.c3p0.ComboPooledDataSource 是下圖中的jar包
dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
(相當於實例化一個ComboPooledDataSource的對象dataSource)
dataSource.driverClass=com.mysql.jdbc.Driver
(相當於對象dataSource調用ComboPooledDataSource類中的setdiverClass方法,將mysql驅動設置進去)
jdbcRealm.dataSource=$dataSource
(將dataSource=com.mchange.v2.c3p0.ComboPooledDataSource中的dataSource對象賦值給
jdbcRealm.dataSource,用$相當於將dataSource對象引用過去。jdbcRealm點後的這個dataSource是下圖中的setDataSource方法參數
將jdbcRealm放入securityManager中,securityManager可以放多個屬性用逗號隔開。
d、下來package com.guo.shiro.HelloWorld.java中代碼
import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.Factory; public class HelloWorld { public static void main(String[] args) { // 讀取配置文件,初始化SecurityManager工廠 Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:jdbc_reaml.ini"); // 獲取securityManager實例 SecurityManager securityManager=factory.getInstance(); // 把securityManager實例綁定到SecurityUtils SecurityUtils.setSecurityManager(securityManager); // 得到當前執行的用戶 Subject currentUser=SecurityUtils.getSubject(); // 創建token令牌,用戶名/密碼 UsernamePasswordToken token=new UsernamePasswordToken("Robin", "123456"); try{ // 身份認證 currentUser.login(token); System.out.println("身份認證成功!"); }catch(AuthenticationException e){ e.printStackTrace(); System.out.println("身份認證失敗!"); } // 退出 currentUser.logout(); } }
5、錯誤
建表名為users ,不能建為t_user會報錯
Shiro安全框架簡介以及身份驗證