Apache Shiro 是 Java 的一個安全(權限)架構。相比于spring security 更加簡單,而且夠用。
• Shiro 可以非常容易的開發出足夠好的應用,其不僅可以用在
JavaSE 環境,也可以用在 JavaEE 環境。
• Shiro 可以完成:認證、授權、加密、會話管理、與Web 內建、 緩存
等。
• 下載下傳:
http://shiro.apache.org/•Authentication:身份認證/登入,驗證使用者是不是擁有相應的身份;
• Authorization:授權,即權限驗證,驗證某個已認證的使用者是否擁有某個權限;即判斷用
戶是否能進行什麼操作,如:驗證某個使用者是否擁有某個角色。或者細粒度的驗證某個使用者
對某個資源是否具有某個權限;
• Session Manager:會話管理,即使用者登入後就是一次會話,在沒有退出之前,它的所有
資訊都在會話中;會話可以是普通 JavaSE 環境,也可以是 Web 環境的;
• Cryptography:加密,保護資料的安全性,如密碼加密存儲到資料庫,而不是明文存儲;
• Web Support:Web 支援,可以非常容易的內建到Web 環境;
• Caching:緩存,比如使用者登入後,其使用者資訊、擁有的角色/權限不必每次去查,這樣可
以提高效率;
• Concurrency:Shiro 支援多線程應用的并發驗證,即如在一個線程中開啟另一個線程,能
把權限自動傳播過去;
• Testing:提供測試支援;
• Run As:允許一個使用者假裝為另一個使用者(如果他們允許)的身份進行通路;
• Remember Me:記住我,這個是非常常見的功能,即一次登入後,下次再來的話不用登
錄了
下面是shiro的hello world程式。
你需要引入相關jar。
[users]
#使用者'root' 的密碼是 'secret' 角色是'admin'
root = secret, admin
#使用者'guest' 的密碼是 'guest' 角色是'guest'
guest = guest, guest
#使用者jk,密碼是jinkai,角色有2個role1和role2
jk = jinkai, role1,role2
[roles]
#角色admin 用通配符*辨別
admin = *
# 角色role1 可以對fuck做任何操作:
role1 = fuck:*
# goodguy 這個角色可以對使用者zhangsan進行删除操作
goodguy = user:delete:zhangsan
package com.shiro.helloworld;
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;
public class Quickstart {
private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);
public static void main(String[] args) {
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//擷取目前的subject
Subject currentUser = SecurityUtils.getSubject();
// 測試使用session,沒有web或者ejb容器的環境也可以。
Session session = currentUser.getSession();
session.setAttribute("someKey", "aValue");
String value = (String) session.getAttribute("someKey");
if (value.equals("aValue")) {
log.info("---> Retrieved the correct value! [" + value + "]");
}
// 測試目前使用者是否已經被認證,即是否正常登入。
if (!currentUser.isAuthenticated()) {
UsernamePasswordToken token = new UsernamePasswordToken("jk", "jinkai");
// rememberme
token.setRememberMe(true);
try {
//執行登入
currentUser.login(token);
}
// 若沒有指定賬戶,則 shiro抛出UnknownAccountException異常.
catch (UnknownAccountException uae) {
log.info("----> There is no user with username of " + token.getPrincipal());
return;
}
// 若賬戶存在,但是密碼不比對,則 shiro 抛出 IncorrectCredentialsException
catch (IncorrectCredentialsException ice) {
log.info("----> Password for account " + token.getPrincipal() + " was incorrect!");
return;
}
// 使用者被鎖定,抛出 LockedAccountException
catch (LockedAccountException lae) {
log.info("The account for username " + token.getPrincipal() + " is locked. " +
"Please contact your administrator to unlock it.");
}
// 所有認證時異常的父類
catch (AuthenticationException ae) {
}
}
log.info("----> User [" + currentUser.getPrincipal() + "] logged in successfully.");
//測試是否有某個角色
if (currentUser.hasRole("role1")) {
log.info("----> 有role1角色!");
} else {
log.info("---->沒有role1角色!");
return;
}
// 測試使用者是否具備某一行為。
if (currentUser.isPermitted("fuck:up")) {
log.info("----> You can fuck up.");
} else {
log.info("Sorry, you cannot.");
}
//測試使用者是否具備某一行為,更具體。
if (currentUser.isPermitted("user:delete:zhangsan")) {
log.info("----> You can delete zhangsan - have fun!");
} else {
log.info("Sorry, you aren't allowed to delete zhangsan!");
}
//all done - 退出!
System.out.println("---->" + currentUser.isAuthenticated());
currentUser.logout();
System.out.println("---->" + currentUser.isAuthenticated());
System.exit(0);
}
}