簡介
Shiro是一個強大的簡單易用的Java安全框架,主要用來更便捷的認證,授權(quán),加密,會話管理。Shiro首要的和最重要的目標就是容易使用并且容易理解。
Shiro是一個有許多特性的全面的安全框架,下面這幅圖可以了解Shiro的特性:

可以看出shiro除了基本的認證,授權(quán),會話管理,加密之外,還有許多額外的特性。
Shiro架構(gòu)
從大的角度來看,Shiro有三個主要的概念:Subject,SecurityManager,Realms,下面這幅圖可以看到這些原件之間的交互。

Subject:翻譯為主角,當前參與應(yīng)用安全部分的主角??梢允怯脩?,可以試第三方服務(wù),可以是cron 任務(wù),或者任何東西。主要指一個正在與當前軟件交互的東西。
所有Subject都需要SecurityManager,當你與Subject進行交互,這些交互行為實際上被轉(zhuǎn)換為與SecurityManager的交互SecurityManager:安全管理員,Shiro架構(gòu)的核心,它就像Shiro內(nèi)部所有原件的保護傘。然而一旦配置了SecurityManager,SecurityManager就用到的比較少,開發(fā)者大部分時間都花在Subject上面。
請記得,當你與Subject進行交互的時候,實際上是SecurityManager在背后幫你舉起Subject來做一些安全操作。Realms:Realms作為Shiro和你的應(yīng)用的連接橋,當需要與安全數(shù)據(jù)交互的時候,像用戶賬戶,或者訪問控制,Shiro就從一個或多個Realms中查找。
Shiro提供了一些可以直接使用的Realms,如果默認的Realms不能滿足你的需求,你也可以定制自己的Realms
更細節(jié)的架構(gòu)

創(chuàng)建Shiro應(yīng)用
使用Idea創(chuàng)建一個Maven項目
Pom.xml中添加如下依賴:
<dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.6.1</version>
</dependency>
</dependencies>
任意創(chuàng)建一個包,在里面創(chuàng)建一個Tutorial類
package me.aihe;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Tutorial {
private static final transient Logger log = LoggerFactory.getLogger(Tutorial.class);
public static void main(String[] args) {
log.info("My First Apache Shiro Application");
System.exit(0);
}
}
使用Shiro
Shiro提供了一個通用的方案通過 INI 進行配置 ,當然也可以通過XML,YMAL,JSON等進行配置。
在resource目錄下面,創(chuàng)建一個shiro.ini的文件。內(nèi)容如下:
# -----------------------------------------------------------------------------
# Users and their (optional) assigned roles
# username = password, role1, role2, ..., roleN
# -----------------------------------------------------------------------------
[users]
root = secret, admin
guest = guest, guest
presidentskroob = 12345, president
darkhelmet = ludicrousspeed, darklord, schwartz
aihe = aihe, goodguy, client
# -----------------------------------------------------------------------------
# Roles with assigned permissions
# roleName = perm1, perm2, ..., permN
# -----------------------------------------------------------------------------
[roles]
admin = *
client = look:*
goodguy = winnebago:drive:eagle5
引用Shiro.ini配置進行測試
現(xiàn)在改變我們的Tutorial類文件,內(nèi)容如下
package me.aihe;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Created by aihe on 2017/6/14.
*/
public class Tutorial {
private static final transient Logger log = LoggerFactory.getLogger(Tutorial.class);
public static void main(String[] args) {
log.info("My First Apache Shiro Application");
//1. 這里的SecurityManager是org.apache.shiro.mgt.SecurityManager,而不是java.lang.SecurityManager
// 加載配置文件
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
//2.解析配置文件,并且返回一些SecurityManger實例
SecurityManager securityManager = factory.getInstance();
//3.設(shè)置SecurityManager到靜態(tài)內(nèi)存區(qū),單例模式
SecurityUtils.setSecurityManager(securityManager);
// 安全操作
Subject currentUser = SecurityUtils.getSubject();
// 在應(yīng)用的當前會話中設(shè)置屬性
Session session = currentUser.getSession();
session.setAttribute("key","value");
//當前我們的用戶是匿名的用戶,我們嘗試進行登錄,
if (!currentUser.isAuthenticated()){
UsernamePasswordToken token = new UsernamePasswordToken("aihe", "aihe");
//this is all you have to do to support 'remember me' (no config - built in!):
token.setRememberMe(true);
//嘗試進行登錄用戶,如果登錄失敗了,我們進行一些處理
try{
currentUser.login(token);
//當我們獲登錄用戶之后
log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");
// 查看用戶是否有指定的角色
if ( currentUser.hasRole( "client" ) ) {
log.info("Look is in your role" );
} else {
log.info( "....." );
}
// 查看用戶是否有某個權(quán)限
if ( currentUser.isPermitted( "look:desk" ) ) {
log.info("You can look. Use it wisely.");
} else {
log.info("Sorry, you can't look.");
}
if ( currentUser.isPermitted( "winnebago:drive:eagle5" ) ) {
log.info("You are permitted to 'drive' the 'winnebago' with license plate (id) 'eagle5'. " +
"Here are the keys - have fun!");
} else {
log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
}
//登出
currentUser.logout();
}
catch ( UnknownAccountException uae ) {
//賬戶不存在的操作
} catch ( IncorrectCredentialsException ice ) {
//密碼不正確
} catch ( LockedAccountException lae ) {
//用戶被鎖定了
} catch ( AuthenticationException ae ) {
//無法判斷的情形
}
}
System.exit(0);
}
}
總結(jié)
這個相對來說是一個簡單的程序,但也證明了一些shiro的基本用法,我們可以通過shiro進行認證,權(quán)限控制等。想要了解更多shiro的用法,請參考Shiro的官方文檔