Shiro快速入門

一.Shiro簡介

  Shiro框架是和spring security框架作用差不多的一個安全認證授權框架,但它更加的輕便和簡單,越來越多的企業在使用它進行角色權限,安全認證等方面功能的管理.

二.主要架構閱覽

Shrio架構圖

  Subject 主體,既可以代表用戶,也可以代表程序(網絡爬蟲等),它需要訪問系統,系統則需要對其進行認證和授權.

? ? ? ? SecurityManager 安全管理,用戶請求Url,對應于一個Subject對象,由SecurityManager統一對Subject進行認證和授權.(父)

? ? ? ? Authenricator 認證部分,主要對Subject進行認證,Subject的信息在shrio中是通過AuthenticationToken對象來儲存,由Authenrication進行驗證管理.(子)

  Authorizer 授權部分,Subject認證后,由它來對其授予對應角色權限.(子)

  SessionManager Shiro的session管理方式,Shiro提供了一個專門管理session的方式,通常的web程序中的session是HttpSession的對象,是由web容器來管理的.

  SessionDao session的接口,Shiro通過它來管理session數據,個性化的session數據儲存需要使用sessionDao.

  CacheManager ?緩存管理工具,主要對session數據和授權數據進行緩存,減小數據庫的訪問壓力.可以通過和ehcache的整合對緩存數據進行管理.

  Pluggable Realms 可擴展領域,相當于數據源,我們通過上面內容可以大致了解到Shiro的工作原理,但Shiro是怎樣得知Subject的信息和數據庫的信息是否匹配呢?Shiro這里就提供了一個realms的概念,它的作用就是得到數據庫中的信息.這個realm是可以多個并且可以自定義,只需繼承AuthorizingRealm這個接口就可以了.

  注意:對Subject進行認證和授權都需要調用realm,所以realm不僅僅相當于數據源,更加包含了認證和授權的一種邏輯.

  Cryptography ?密碼演算法,一個密碼管理工具,提供了一套加密/解密的組件.比如長用的散列,加/解密等功能,日常練習所使用的md5算法其實是一種散列算法,只能加密,不能解密.

可見Shrio的核心部分還是認證和授權部分,其他都是圍繞這倆部分進行的,只需理解了這兩部分就可以進行開發了.

三.Shiro認證實例(入門案例)

Shiro處理一個Subject流程圖


Shrio流程圖1

Shiro處理認證流程圖,相當于上圖的擴充和細化


Shrio流程圖1

可見,Shiro處理流程是一級一級的調用,主要是調用Authentication來進行驗證,最后還是需要使用realm來進行身份驗證(realm后面會提).

有了基本的執行流程圖,大概就能懂了Shiro的運行原理,接下來實踐一下,首先新建一個普通的java工程,導入shiro-core.jar包


Shrio jar包

這個作為入門程序導入這一個核心包就行了,建立測試代碼,我這里用的是junit,也可以直接main()走起.代碼如下:

//模擬用戶登錄登出

@Test

public void demo1(){

//創建SecurityManager工廠,生成SecurityManager環境(通過shrio的ini文件),      Factory<SecurityManager> ?factory  =  new          IniSecurityManagerFactory("classpath:shrio.ini");

//創建SecurityManager

SecurityManager manager= factory.getInstance();

//將當前環境設為SecurityManager

SecurityUtils.setSecurityManager(manager);

//模擬Subject

Subject subject = SecurityUtils.getSubject();

//提交認證是說攜帶的信息儲存在 token 中

UsernamePasswordToken token = new UsernamePasswordToken("Floder", "Floder");

try {

?//模擬獲取登陸

?subject.login(token);

} catch (AuthenticationException e) {

e.printStackTrace();

}

//判斷是否認證通過

boolean isOk = subject.isAuthenticated();

System.out.println("用戶是否登錄:"+isOk);

//模擬用戶退出登陸

subject.logout();

isOk = subject.isAuthenticated();

System.out.println("用戶是否登錄:"+isOk);

}

這里有幾點要說明的,

1.這里需要配置Shiro的配置文件,我看了一下源碼,是通過InputStream來掃描配置文件,所以文件名任意.需要表明路徑即可,classpath即為項目的src目錄下,Shiro.ini的配置如下

#自定義數據源 格式 用戶名=密碼

[users]

Floder=Floder

2.構建工廠時Factory的泛型SecurityManager需要是用的是SecurityManager的接口,因為java.lang.SecurityManager也存在...

Shiro授權流程圖

Shiro授權流程圖

和認證流程圖差不多,不過這個調用的是Authrizer模塊

在進行實際操作前,需要理解Shiro的兩個重要概念

1.基于角色管理:根據用戶的相應角色授予相應的資源權限,但這樣做有點不好的地方就是每新增一個角色都要對角色進行相應的資源權限管理(超級QQ,QQ會員),在實際開發中太過麻煩,不經常使用.

2.基于資源管理:對資源的訪問需要一定的權限,這樣的話每新增一個角色只需在權限對應的資源進行角色新增即可.特別方便.

測試代碼:

//模擬用戶認證授權

@Test

public void testAuthorizer(){

//創建SecurityManager工廠,生成SecurityManager環境(通過shrio的ini文件),//通過ini配置文件創建

securityManagerFactory factory = new IniSecurityManagerFactory("classpath:shrio-permission.ini");

//創建SecurityManager

SecurityManager manager= factory.getInstance();

//將當前環境設為SecurityManager

SecurityUtils.setSecurityManager(manager);

//模擬Subject

Subject subject = SecurityUtils.getSubject();

//提交認證是說攜帶的信息儲存在 Token 中

UsernamePasswordToken token = new UsernamePasswordToken("Floder", "Floder");

//模擬獲取登陸

try {

subject.login(token);

} catch (AuthenticationException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

//基于角色判斷

//判斷已認證用戶是否擁有role1角色

boolean isHasRole = subject.hasRole("role2");

System.out.println("判斷已認證用戶是否擁有role2角色 "+isHasRole);

//也可以判斷已認證用戶是否有多個角色

boolean isHasAllRoles = subject.hasAllRoles(Arrays.asList("role1","role2"));

System.out.println("判斷已認證用戶是否有多個角色"+isHasAllRoles);

//基于資源判斷

//判斷已認證用戶的資源是否擁有對應單個的操作

boolean isPermitted = subject.isPermitted("user:create");

System.out.println("判斷已認證用戶的資源是否擁有對應的單個操作 "+isPermitted);

//判斷已認證用戶的資源是否擁有對應的多個操作

boolean isPermittedAll = subject.isPermittedAll("user:create","user:update");

System.out.println("判斷已認證用戶的資源是否擁有對應的多個操作 "+isPermittedAll);

}

這里需要新建一個Shrio-permission.ini配置文件,具體信息如下:

#用戶對應的角色

#用戶Floder擁有角色role1和role2

[users]

Floder = Floder,role1,role2

floder=floder,role2

#角色對應的資源權限

[roles]

#權限標識符符號規則 資源:操作:實例 user:create:01 表示對用戶資源實例01進行create操作

#user:create 表示對資源進行create操作,相當于user:create:*

#user:*:01 表示對用戶資源實例01進行所有操作

role1=user:create,user:update

role2 = user:create

  和Shrio認證一樣,只不過這里的user新增的角色欄,另外還對[roles]進行了相應的權限設置,看代碼即可,注釋都寫的清清楚楚

  通過這兩個認證和授權實例,大概能理解了ini文件起的作用,一般是相當于數據源,在Shiro中就是Realm,注意,Realm不僅僅起數據源的作用,更加包含了認證和授權的一種邏輯.重要的事說兩遍

四.自定義Realm實現


在上一節中我們并沒有自定義realm,那它是怎樣調用認證和授權的一種邏輯呢?原來,Shiro默認提供了一個IniRealm實現,但我們知道,可以自定義Realm實現來實現我們的需求,只需實現AuthorizingRealm接口就行了(常用是這個),Realm有多種接口:

Realm結構圖


Realm繼承關系圖


具體繼承那個接口看需求,我們測試的時候就使用AuthorizingRealm

自定義UserRealm:

//設置realm名,需要繼承setName()方法

@Override

public void setName(String name) {

super.setName("userName");

}

//認證方法

@Override

protected AuthenticationInfo doGetAuthenticationInfo(

AuthenticationToken token) throws AuthenticationException {

//得到token的用戶信息

String userId = (String) token.getPrincipal();

//模擬數據庫返回數據,如果不存在就返回null

//.......

//模擬數據庫返回數據,存在就返回一個credentials

String password = "Floder";

SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userId, password, this.getName());

return info;

}

//授權方法(依賴于上面的認證信息)

@Override

protected AuthorizationInfo doGetAuthorizationInfo(

PrincipalCollection principals) {

String userId = (String) principals.getPrimaryPrincipal();

//模擬從數據庫得來的角色信息,

List<String> listPermission = new ArrayList<String>();

//模擬用戶創建權限

listPermission.add("user:create");

//模擬用戶添加權限

listPermission.add("user:update");

//這里的info使用的是SimpleAuthorizationInfo

SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

//SimpleAuthorizationInfo攜帶的是數據庫返回的信息,數據實現的是collection接口的玩意info.addStringPermissions(listPermission);

return info;

?  這里如果需要模擬null就很簡單了,寫個if()判斷即可,這里的info信息我們實現的是SimpleAuthenticationInfo接口和SimpleAuthenticationInfo授權接口,

? ? ? 我們知道realm是與數據庫打交道的,由于有了自定義realm,我們就不用在ini文件中寫[users]了,所以修改Shiro.ini文件的信息:

[main]

#聲明我們自定義的realm

userRealm=com.floder.junit.realm.UserRealm

#將realm放入SecurityManager中

SecurityManager.realms=$userRealm

好了,準備工作都完成了,接下來開始測試,認證登陸模擬和上一節模擬登陸代碼相同,授權測試代碼需要修改部分代碼:

try {

//模擬獲取登陸

subject.login(token);

} catch (AuthenticationException e) {

e.printStackTrace();

}

//基于資源判斷

//判斷已認證用戶的資源是否擁有對應的操作

boolean isPermitted = subject.isPermitted("user:create");

System.out.println("判斷已認證用戶的資源是否擁有對應的操作 "+isPermitted);

//使用check方法進行授權,如果不通過則拋出異常

subject.checkPermission("item:add");//這是需要添加的,基于角色就不需要測試了

注釋這么清楚,就不解釋了.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,179評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,444評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,948評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,185評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,717評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,794評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,414評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,750評論 2 370

推薦閱讀更多精彩內容