日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Realm及相关对象——《跟我学Shiro》

發(fā)布時(shí)間:2025/3/21 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Realm及相关对象——《跟我学Shiro》 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

6.1 Realm

【2.5 Realm】及【3.5 Authorizer】部分都已經(jīng)詳細(xì)介紹過(guò)Realm了,接下來(lái)再來(lái)看一下一般真實(shí)環(huán)境下的Realm如何實(shí)現(xiàn)。

??

1、定義實(shí)體及關(guān)系

即用戶-角色之間是多對(duì)多關(guān)系,角色-權(quán)限之間是多對(duì)多關(guān)系;且用戶和權(quán)限之間通過(guò)角色建立關(guān)系;在系統(tǒng)中驗(yàn)證時(shí)通過(guò)權(quán)限驗(yàn)證,角色只是權(quán)限集合,即所謂的顯示角色;其實(shí)權(quán)限應(yīng)該對(duì)應(yīng)到資源(如菜單、URL、頁(yè)面按鈕、Java方法等)中,即應(yīng)該將權(quán)限字符串存儲(chǔ)到資源實(shí)體中,但是目前為了簡(jiǎn)單化,直接提取一個(gè)權(quán)限表,【綜合示例】部分會(huì)使用完整的表結(jié)構(gòu)。

?

用戶實(shí)體包括:編號(hào)(id)、用戶名(username)、密碼(password)、鹽(salt)、是否鎖定(locked);是否鎖定用于封禁用戶使用,其實(shí)最好使用Enum字段存儲(chǔ),可以實(shí)現(xiàn)更復(fù)雜的用戶狀態(tài)實(shí)現(xiàn)。

角色實(shí)體包括:、編號(hào)(id)、角色標(biāo)識(shí)符(role)、描述(description)、是否可用(available);其中角色標(biāo)識(shí)符用于在程序中進(jìn)行隱式角色判斷的,描述用于以后再前臺(tái)界面顯示的、是否可用表示角色當(dāng)前是否激活。

權(quán)限實(shí)體包括:編號(hào)(id)、權(quán)限標(biāo)識(shí)符(permission)、描述(description)、是否可用(available);含義和角色實(shí)體類似不再闡述。

?

另外還有兩個(gè)關(guān)系實(shí)體:用戶-角色實(shí)體(用戶編號(hào)、角色編號(hào),且組合為復(fù)合主鍵);角色-權(quán)限實(shí)體(角色編號(hào)、權(quán)限編號(hào),且組合為復(fù)合主鍵)。

?

sql及實(shí)體請(qǐng)參考源代碼中的sql\shiro.sql 和 com.github.zhangkaitao.shiro.chapter6.entity對(duì)應(yīng)的實(shí)體。

?

2、環(huán)境準(zhǔn)備

為了方便數(shù)據(jù)庫(kù)操作,使用了“org.springframework: spring-jdbc: 4.0.0.RELEASE”依賴,雖然是spring4版本的,但使用上和spring3無(wú)區(qū)別。其他依賴請(qǐng)參考源碼的pom.xml。

?

3、定義Service及Dao

為了實(shí)現(xiàn)的簡(jiǎn)單性,只實(shí)現(xiàn)必須的功能,其他的可以自己實(shí)現(xiàn)即可。

?

PermissionService

Java代碼??

  • public?interface?PermissionService?{??
  • ????public?Permission?createPermission(Permission?permission);??
  • ????public?void?deletePermission(Long?permissionId);??
  • }??
  • 實(shí)現(xiàn)基本的創(chuàng)建/刪除權(quán)限。

    ?

    RoleService?

    Java代碼??

  • public?interface?RoleService?{??
  • ????public?Role?createRole(Role?role);??
  • ????public?void?deleteRole(Long?roleId);??
  • ????//添加角色-權(quán)限之間關(guān)系??
  • ????public?void?correlationPermissions(Long?roleId,?Long...?permissionIds);??
  • ????//移除角色-權(quán)限之間關(guān)系??
  • ????public?void?uncorrelationPermissions(Long?roleId,?Long...?permissionIds);//??
  • }???
  • 相對(duì)于PermissionService多了關(guān)聯(lián)/移除關(guān)聯(lián)角色-權(quán)限功能。

    ?

    UserService?

    Java代碼??

  • public?interface?UserService?{??
  • ????public?User?createUser(User?user);?//創(chuàng)建賬戶??
  • ????public?void?changePassword(Long?userId,?String?newPassword);//修改密碼??
  • ????public?void?correlationRoles(Long?userId,?Long...?roleIds);?//添加用戶-角色關(guān)系??
  • ????public?void?uncorrelationRoles(Long?userId,?Long...?roleIds);//?移除用戶-角色關(guān)系??
  • ????public?User?findByUsername(String?username);//?根據(jù)用戶名查找用戶??
  • ????public?Set<String>?findRoles(String?username);//?根據(jù)用戶名查找其角色??
  • ????public?Set<String>?findPermissions(String?username);?//根據(jù)用戶名查找其權(quán)限??
  • }???
  • 此處使用findByUsername、findRoles及findPermissions來(lái)查找用戶名對(duì)應(yīng)的帳號(hào)、角色及權(quán)限信息。之后的Realm就使用這些方法來(lái)查找相關(guān)信息。

    ?

    UserServiceImpl??

    Java代碼??

  • public?User?createUser(User?user)?{??
  • ????//加密密碼??
  • ????passwordHelper.encryptPassword(user);??
  • ????return?userDao.createUser(user);??
  • }??
  • public?void?changePassword(Long?userId,?String?newPassword)?{??
  • ????User?user?=userDao.findOne(userId);??
  • ????user.setPassword(newPassword);??
  • ????passwordHelper.encryptPassword(user);??
  • ????userDao.updateUser(user);??
  • }???
  • 在創(chuàng)建賬戶及修改密碼時(shí)直接把生成密碼操作委托給PasswordHelper。

    ?

    PasswordHelper

    Java代碼??

  • public?class?PasswordHelper?{??
  • ????private?RandomNumberGenerator?randomNumberGenerator?=??
  • ?????new?SecureRandomNumberGenerator();??
  • ????private?String?algorithmName?=?"md5";??
  • ????private?final?int?hashIterations?=?2;??
  • ????public?void?encryptPassword(User?user)?{??
  • ????????user.setSalt(randomNumberGenerator.nextBytes().toHex());??
  • ????????String?newPassword?=?new?SimpleHash(??
  • ????????????????algorithmName,??
  • ????????????????user.getPassword(),??
  • ????????????????ByteSource.Util.bytes(user.getCredentialsSalt()),??
  • ????????????????hashIterations).toHex();??
  • ????????user.setPassword(newPassword);??
  • ????}??
  • }???
  • 之后的CredentialsMatcher需要和此處加密的算法一樣。user.getCredentialsSalt()輔助方法返回username+salt。

    ?

    為了節(jié)省篇幅,對(duì)于DAO/Service的接口及實(shí)現(xiàn),具體請(qǐng)參考源碼com.github.zhangkaitao.shiro.chapter6。另外請(qǐng)參考Service層的測(cè)試用例com.github.zhangkaitao.shiro.chapter6.service.ServiceTest。

    ?

    4、定義Realm

    RetryLimitHashedCredentialsMatcher?

    和第五章的一樣,在此就不羅列代碼了,請(qǐng)參考源碼com.github.zhangkaitao.shiro.chapter6.credentials.RetryLimitHashedCredentialsMatcher。

    ??

    UserRealm

    另外請(qǐng)參考Service層的測(cè)試用例com.github.zhangkaitao.shiro.chapter6.service.ServiceTest。?

    Java代碼??

  • public?class?UserRealm?extends?AuthorizingRealm?{??
  • ????private?UserService?userService?=?new?UserServiceImpl();??
  • ????protected?AuthorizationInfo?doGetAuthorizationInfo(PrincipalCollection?principals)?{??
  • ????????String?username?=?(String)principals.getPrimaryPrincipal();??
  • ????????SimpleAuthorizationInfo?authorizationInfo?=?new?SimpleAuthorizationInfo();??
  • ????????authorizationInfo.setRoles(userService.findRoles(username));??
  • ????????authorizationInfo.setStringPermissions(userService.findPermissions(username));??
  • ????????return?authorizationInfo;??
  • ????}??
  • ????protected?AuthenticationInfo?doGetAuthenticationInfo(AuthenticationToken?token)?throws?AuthenticationException?{??
  • ????????String?username?=?(String)token.getPrincipal();??
  • ????????User?user?=?userService.findByUsername(username);??
  • ????????if(user?==?null)?{??
  • ????????????throw?new?UnknownAccountException();//沒(méi)找到帳號(hào)??
  • ????????}??
  • ????????if(Boolean.TRUE.equals(user.getLocked()))?{??
  • ????????????throw?new?LockedAccountException();?//帳號(hào)鎖定??
  • ????????}??
  • ????????//交給AuthenticatingRealm使用CredentialsMatcher進(jìn)行密碼匹配,如果覺(jué)得人家的不好可以在此判斷或自定義實(shí)現(xiàn)??
  • ????????SimpleAuthenticationInfo?authenticationInfo?=?new?SimpleAuthenticationInfo(??
  • ????????????????user.getUsername(),?//用戶名??
  • ????????????????user.getPassword(),?//密碼??
  • ????????????????ByteSource.Util.bytes(user.getCredentialsSalt()),//salt=username+salt??
  • ????????????????getName()??//realm?name??
  • ????????);??
  • ????????return?authenticationInfo;??
  • ????}??
  • }???
  • 1、UserRealm父類AuthorizingRealm將獲取Subject相關(guān)信息分成兩步:獲取身份驗(yàn)證信息(doGetAuthenticationInfo)及授權(quán)信息(doGetAuthorizationInfo);

    2、doGetAuthenticationInfo獲取身份驗(yàn)證相關(guān)信息:首先根據(jù)傳入的用戶名獲取User信息;然后如果user為空,那么拋出沒(méi)找到帳號(hào)異常UnknownAccountException;如果user找到但鎖定了拋出鎖定異常LockedAccountException;最后生成AuthenticationInfo信息,交給間接父類AuthenticatingRealm使用CredentialsMatcher進(jìn)行判斷密碼是否匹配,如果不匹配將拋出密碼錯(cuò)誤異常IncorrectCredentialsException;另外如果密碼重試此處太多將拋出超出重試次數(shù)異常ExcessiveAttemptsException;在組裝SimpleAuthenticationInfo信息時(shí),需要傳入:身份信息(用戶名)、憑據(jù)(密文密碼)、鹽(username+salt),CredentialsMatcher使用鹽加密傳入的明文密碼和此處的密文密碼進(jìn)行匹配。

    3、doGetAuthorizationInfo獲取授權(quán)信息:PrincipalCollection是一個(gè)身份集合,因?yàn)槲覀儸F(xiàn)在就一個(gè)Realm,所以直接調(diào)用getPrimaryPrincipal得到之前傳入的用戶名即可;然后根據(jù)用戶名調(diào)用UserService接口獲取角色及權(quán)限信息。

    ?

    5、測(cè)試用例

    為了節(jié)省篇幅,請(qǐng)參考測(cè)試用例com.github.zhangkaitao.shiro.chapter6.realm.UserRealmTest。包含了:登錄成功、用戶名錯(cuò)誤、密碼錯(cuò)誤、密碼超出重試次數(shù)、有/沒(méi)有角色、有/沒(méi)有權(quán)限的測(cè)試。

    ?

    6.2 AuthenticationToken

    AuthenticationToken用于收集用戶提交的身份(如用戶名)及憑據(jù)(如密碼):

    Java代碼??

  • public?interface?AuthenticationToken?extends?Serializable?{??
  • ????Object?getPrincipal();?//身份??
  • ????Object?getCredentials();?//憑據(jù)??
  • }???
  • 擴(kuò)展接口RememberMeAuthenticationToken:提供了“boolean isRememberMe()”現(xiàn)“記住我”的功能;

    擴(kuò)展接口是HostAuthenticationToken:提供了“String getHost()”方法用于獲取用戶“主機(jī)”的功能。

    ?

    Shiro提供了一個(gè)直接拿來(lái)用的UsernamePasswordToken,用于實(shí)現(xiàn)用戶名/密碼Token組,另外其實(shí)現(xiàn)了RememberMeAuthenticationToken和HostAuthenticationToken,可以實(shí)現(xiàn)記住我及主機(jī)驗(yàn)證的支持。

    ?

    6.3 AuthenticationInfo

    AuthenticationInfo有兩個(gè)作用:

    1、如果Realm是AuthenticatingRealm子類,則提供給AuthenticatingRealm內(nèi)部使用的CredentialsMatcher進(jìn)行憑據(jù)驗(yàn)證;(如果沒(méi)有繼承它需要在自己的Realm中自己實(shí)現(xiàn)驗(yàn)證);

    2、提供給SecurityManager來(lái)創(chuàng)建Subject(提供身份信息);

    ?

    MergableAuthenticationInfo用于提供在多Realm時(shí)合并AuthenticationInfo的功能,主要合并Principal、如果是其他的如credentialsSalt,會(huì)用后邊的信息覆蓋前邊的。

    ?

    比如HashedCredentialsMatcher,在驗(yàn)證時(shí)會(huì)判斷AuthenticationInfo是否是SaltedAuthenticationInfo子類,來(lái)獲取鹽信息。

    ?

    Account相當(dāng)于我們之前的User,SimpleAccount是其一個(gè)實(shí)現(xiàn);在IniRealm、PropertiesRealm這種靜態(tài)創(chuàng)建帳號(hào)信息的場(chǎng)景中使用,這些Realm直接繼承了SimpleAccountRealm,而SimpleAccountRealm提供了相關(guān)的API來(lái)動(dòng)態(tài)維護(hù)SimpleAccount;即可以通過(guò)這些API來(lái)動(dòng)態(tài)增刪改查SimpleAccount;動(dòng)態(tài)增刪改查角色/權(quán)限信息。及如果您的帳號(hào)不是特別多,可以使用這種方式,具體請(qǐng)參考SimpleAccountRealm Javadoc。

    ?

    其他情況一般返回SimpleAuthenticationInfo即可。

    ?

    6.4 PrincipalCollection

    因?yàn)槲覀兛梢栽赟hiro中同時(shí)配置多個(gè)Realm,所以呢身份信息可能就有多個(gè);因此其提供了PrincipalCollection用于聚合這些身份信息:

    Java代碼??

  • public?interface?PrincipalCollection?extends?Iterable,?Serializable?{??
  • ????Object?getPrimaryPrincipal();?//得到主要的身份??
  • ????<T>?T?oneByType(Class<T>?type);?//根據(jù)身份類型獲取第一個(gè)??
  • ????<T>?Collection<T>?byType(Class<T>?type);?//根據(jù)身份類型獲取一組??
  • ????List?asList();?//轉(zhuǎn)換為L(zhǎng)ist??
  • ????Set?asSet();?//轉(zhuǎn)換為Set??
  • ????Collection?fromRealm(String?realmName);?//根據(jù)Realm名字獲取??
  • ????Set<String>?getRealmNames();?//獲取所有身份驗(yàn)證通過(guò)的Realm名字??
  • ????boolean?isEmpty();?//判斷是否為空??
  • }???
  • 因?yàn)镻rincipalCollection聚合了多個(gè),此處最需要注意的是getPrimaryPrincipal,如果只有一個(gè)Principal那么直接返回即可,如果有多個(gè)Principal,則返回第一個(gè)(因?yàn)閮?nèi)部使用Map存儲(chǔ),所以可以認(rèn)為是返回任意一個(gè));oneByType / byType根據(jù)憑據(jù)的類型返回相應(yīng)的Principal;fromRealm根據(jù)Realm名字(每個(gè)Principal都與一個(gè)Realm關(guān)聯(lián))獲取相應(yīng)的Principal。

    ?

    MutablePrincipalCollection是一個(gè)可變的PrincipalCollection接口,即提供了如下可變方法:

    Java代碼??

  • public?interface?MutablePrincipalCollection?extends?PrincipalCollection?{??
  • ????void?add(Object?principal,?String?realmName);?//添加Realm-Principal的關(guān)聯(lián)??
  • ????void?addAll(Collection?principals,?String?realmName);?//添加一組Realm-Principal的關(guān)聯(lián)??
  • ????void?addAll(PrincipalCollection?principals);//添加PrincipalCollection??
  • ????void?clear();//清空??
  • }???
  • 目前Shiro只提供了一個(gè)實(shí)現(xiàn)SimplePrincipalCollection,還記得之前的AuthenticationStrategy實(shí)現(xiàn)嘛,用于在多Realm時(shí)判斷是否滿足條件的,在大多數(shù)實(shí)現(xiàn)中(繼承了AbstractAuthenticationStrategy)afterAttempt方法會(huì)進(jìn)行AuthenticationInfo(實(shí)現(xiàn)了MergableAuthenticationInfo)的merge,比如SimpleAuthenticationInfo會(huì)合并多個(gè)Principal為一個(gè)PrincipalCollection。

    ?

    對(duì)于PrincipalMap是Shiro 1.2中的一個(gè)實(shí)驗(yàn)品,暫時(shí)無(wú)用,具體可以參考其Javadoc。接下來(lái)通過(guò)示例來(lái)看看PrincipalCollection。

    ?

    1、準(zhǔn)備三個(gè)Realm

    MyRealm1

    Java代碼??

  • public?class?MyRealm1?implements?Realm?{??
  • ????@Override??
  • ????public?String?getName()?{??
  • ????????return?"a";?//realm?name?為?“a”??
  • ????}??
  • ????//省略supports方法,具體請(qǐng)見(jiàn)源碼??
  • ????@Override??
  • ????public?AuthenticationInfo?getAuthenticationInfo(AuthenticationToken?token)?throws?AuthenticationException?{??
  • ????????return?new?SimpleAuthenticationInfo(??
  • ????????????????"zhang",?//身份?字符串類型??
  • ????????????????"123",???//憑據(jù)??
  • ????????????????getName()?//Realm?Name??
  • ????????);??
  • ????}??
  • }??
  • ?????????

    MyRealm2?

    和MyRealm1完全一樣,只是Realm名字為b。

    ??

    MyRealm3

    Java代碼??

  • public?class?MyRealm3?implements?Realm?{??
  • ????@Override??
  • ????public?String?getName()?{??
  • ????????return?"c";?//realm?name?為?“c”??
  • ????}??
  • ????//省略supports方法,具體請(qǐng)見(jiàn)源碼??
  • ????@Override??
  • ????public?AuthenticationInfo?getAuthenticationInfo(AuthenticationToken?token)?throws?AuthenticationException?{??
  • ????????User?user?=?new?User("zhang",?"123");??
  • ????????return?new?SimpleAuthenticationInfo(??
  • ????????????????user,?//身份?User類型??
  • ????????????????"123",???//憑據(jù)??
  • ????????????????getName()?//Realm?Name??
  • ????????);??
  • ????}??
  • }???
  • 和MyRealm1同名,但返回的Principal是User類型。

    ?

    2、ini配置(shiro-multirealm.ini)

    Java代碼??

  • [main]??
  • realm1=com.github.zhangkaitao.shiro.chapter6.realm.MyRealm1??
  • realm2=com.github.zhangkaitao.shiro.chapter6.realm.MyRealm2??
  • realm3=com.github.zhangkaitao.shiro.chapter6.realm.MyRealm3??
  • securityManager.realms=$realm1,$realm2,$realm3???
  • 3、測(cè)試用例(com.github.zhangkaitao.shiro.chapter6.realm.PrincialCollectionTest)

    因?yàn)槲覀兊腞ealm中沒(méi)有進(jìn)行身份及憑據(jù)驗(yàn)證,所以相當(dāng)于身份驗(yàn)證都是成功的,都將返回:

    Java代碼??

  • Object?primaryPrincipal1?=?subject.getPrincipal();??
  • PrincipalCollection?princialCollection?=?subject.getPrincipals();??
  • Object?primaryPrincipal2?=?princialCollection.getPrimaryPrincipal();???
  • 我們可以直接調(diào)用subject.getPrincipal獲取PrimaryPrincipal(即所謂的第一個(gè));或者通過(guò)getPrincipals獲取PrincipalCollection;然后通過(guò)其getPrimaryPrincipal獲取PrimaryPrincipal。

    ?

    Java代碼??

  • Set<String>?realmNames?=?princialCollection.getRealmNames();??
  • 獲取所有身份驗(yàn)證成功的Realm名字。??????

    ?

    Java代碼??

  • Set<Object>?principals?=?princialCollection.asSet();?//asList和asSet的結(jié)果一樣??
  • 將身份信息轉(zhuǎn)換為Set/List,即使轉(zhuǎn)換為L(zhǎng)ist,也是先轉(zhuǎn)換為Set再完成的。

    ?

    Java代碼??

  • Collection<User>?users?=?princialCollection.fromRealm("c");??
  • 根據(jù)Realm名字獲取身份,因?yàn)镽ealm名字可以重復(fù),所以可能多個(gè)身份,建議Realm名字盡量不要重復(fù)。

    ?

    6.4 AuthorizationInfo

    AuthorizationInfo用于聚合授權(quán)信息的:

    Java代碼??

  • public?interface?AuthorizationInfo?extends?Serializable?{??
  • ????Collection<String>?getRoles();?//獲取角色字符串信息??
  • ????Collection<String>?getStringPermissions();?//獲取權(quán)限字符串信息??
  • ????Collection<Permission>?getObjectPermissions();?//獲取Permission對(duì)象信息??
  • }???
  • 當(dāng)我們使用AuthorizingRealm時(shí),如果身份驗(yàn)證成功,在進(jìn)行授權(quán)時(shí)就通過(guò)doGetAuthorizationInfo方法獲取角色/權(quán)限信息用于授權(quán)驗(yàn)證。

    ?

    Shiro提供了一個(gè)實(shí)現(xiàn)SimpleAuthorizationInfo,大多數(shù)時(shí)候使用這個(gè)即可。

    ?

    對(duì)于Account及SimpleAccount,之前的【6.3 AuthenticationInfo】已經(jīng)介紹過(guò)了,用于SimpleAccountRealm子類,實(shí)現(xiàn)動(dòng)態(tài)角色/權(quán)限維護(hù)的。

    ?

    6.5 Subject

    Subject是Shiro的核心對(duì)象,基本所有身份驗(yàn)證、授權(quán)都是通過(guò)Subject完成。

    1、身份信息獲取

    Java代碼??

  • Object?getPrincipal();?//Primary?Principal??
  • PrincipalCollection?getPrincipals();?//?PrincipalCollection???
  • ?

    2、身份驗(yàn)證

    Java代碼??

  • void?login(AuthenticationToken?token)?throws?AuthenticationException;??
  • boolean?isAuthenticated();??
  • boolean?isRemembered();??
  • 通過(guò)login登錄,如果登錄失敗將拋出相應(yīng)的AuthenticationException,如果登錄成功調(diào)用isAuthenticated就會(huì)返回true,即已經(jīng)通過(guò)身份驗(yàn)證;如果isRemembered返回true,表示是通過(guò)記住我功能登錄的而不是調(diào)用login方法登錄的。isAuthenticated/isRemembered是互斥的,即如果其中一個(gè)返回true,另一個(gè)返回false。

    ??

    3、角色授權(quán)驗(yàn)證?

    Java代碼??

  • boolean?hasRole(String?roleIdentifier);??
  • boolean[]?hasRoles(List<String>?roleIdentifiers);??
  • boolean?hasAllRoles(Collection<String>?roleIdentifiers);??
  • void?checkRole(String?roleIdentifier)?throws?AuthorizationException;??
  • void?checkRoles(Collection<String>?roleIdentifiers)?throws?AuthorizationException;??
  • void?checkRoles(String...?roleIdentifiers)?throws?AuthorizationException;???
  • hasRole*進(jìn)行角色驗(yàn)證,驗(yàn)證后返回true/false;而checkRole*驗(yàn)證失敗時(shí)拋出AuthorizationException異常。?

    ?

    4、權(quán)限授權(quán)驗(yàn)證

    Java代碼??

  • boolean?isPermitted(String?permission);??
  • boolean?isPermitted(Permission?permission);??
  • boolean[]?isPermitted(String...?permissions);??
  • boolean[]?isPermitted(List<Permission>?permissions);??
  • boolean?isPermittedAll(String...?permissions);??
  • boolean?isPermittedAll(Collection<Permission>?permissions);??
  • void?checkPermission(String?permission)?throws?AuthorizationException;??
  • void?checkPermission(Permission?permission)?throws?AuthorizationException;??
  • void?checkPermissions(String...?permissions)?throws?AuthorizationException;??
  • void?checkPermissions(Collection<Permission>?permissions)?throws?AuthorizationException;??
  • isPermitted*進(jìn)行權(quán)限驗(yàn)證,驗(yàn)證后返回true/false;而checkPermission*驗(yàn)證失敗時(shí)拋出AuthorizationException。

    ?

    5、會(huì)話

    Java代碼??

  • Session?getSession();?//相當(dāng)于getSession(true)??
  • Session?getSession(boolean?create);????
  • 類似于Web中的會(huì)話。如果登錄成功就相當(dāng)于建立了會(huì)話,接著可以使用getSession獲取;如果create=false如果沒(méi)有會(huì)話將返回null,而create=true如果沒(méi)有會(huì)話會(huì)強(qiáng)制創(chuàng)建一個(gè)。

    ?

    6、退出?

    Java代碼??

  • void?logout();??
  • ?

    7、RunAs??

    Java代碼??

  • void?runAs(PrincipalCollection?principals)?throws?NullPointerException,?IllegalStateException;??
  • boolean?isRunAs();??
  • PrincipalCollection?getPreviousPrincipals();??
  • PrincipalCollection?releaseRunAs();???
  • RunAs即實(shí)現(xiàn)“允許A假設(shè)為B身份進(jìn)行訪問(wèn)”;通過(guò)調(diào)用subject.runAs(b)進(jìn)行訪問(wèn);接著調(diào)用subject.getPrincipals將獲取到B的身份;此時(shí)調(diào)用isRunAs將返回true;而a的身份需要通過(guò)subject. getPreviousPrincipals獲取;如果不需要RunAs了調(diào)用subject. releaseRunAs即可。

    ?

    8、多線程

    Java代碼??

  • <V>?V?execute(Callable<V>?callable)?throws?ExecutionException;??
  • void?execute(Runnable?runnable);??
  • <V>?Callable<V>?associateWith(Callable<V>?callable);??
  • Runnable?associateWith(Runnable?runnable);???
  • 實(shí)現(xiàn)線程之間的Subject傳播,因?yàn)镾ubject是線程綁定的;因此在多線程執(zhí)行中需要傳播到相應(yīng)的線程才能獲取到相應(yīng)的Subject。最簡(jiǎn)單的辦法就是通過(guò)execute(runnable/callable實(shí)例)直接調(diào)用;或者通過(guò)associateWith(runnable/callable實(shí)例)得到一個(gè)包裝后的實(shí)例;它們都是通過(guò):1、把當(dāng)前線程的Subject綁定過(guò)去;2、在線程執(zhí)行結(jié)束后自動(dòng)釋放。

    ?

    Subject自己不會(huì)實(shí)現(xiàn)相應(yīng)的身份驗(yàn)證/授權(quán)邏輯,而是通過(guò)DelegatingSubject委托給SecurityManager實(shí)現(xiàn);及可以理解為Subject是一個(gè)面門。

    ?

    對(duì)于Subject的構(gòu)建一般沒(méi)必要我們?nèi)?chuàng)建;一般通過(guò)SecurityUtils.getSubject()獲取:

    Java代碼??

  • public?static?Subject?getSubject()?{??
  • ????Subject?subject?=?ThreadContext.getSubject();??
  • ????if?(subject?==?null)?{??
  • ????????subject?=?(new?Subject.Builder()).buildSubject();??
  • ????????ThreadContext.bind(subject);??
  • ????}??
  • ????return?subject;??
  • }???
  • 即首先查看當(dāng)前線程是否綁定了Subject,如果沒(méi)有通過(guò)Subject.Builder構(gòu)建一個(gè)然后綁定到現(xiàn)場(chǎng)返回。

    ?

    如果想自定義創(chuàng)建,可以通過(guò):

    Java代碼??

  • new?Subject.Builder().principals(身份).authenticated(true/false).buildSubject()??
  • 這種可以創(chuàng)建相應(yīng)的Subject實(shí)例了,然后自己綁定到線程即可。在new Builder()時(shí)如果沒(méi)有傳入SecurityManager,自動(dòng)調(diào)用SecurityUtils.getSecurityManager獲取;也可以自己傳入一個(gè)實(shí)例。

    ?

    對(duì)于Subject我們一般這么使用:

    1、身份驗(yàn)證(login)

    2、授權(quán)(hasRole*/isPermitted*或checkRole*/checkPermission*)

    3、將相應(yīng)的數(shù)據(jù)存儲(chǔ)到會(huì)話(Session)

    4、切換身份(RunAs)/多線程身份傳播

    5、退出

    ?

    ?

    而我們必須的功能就是1、2、5。到目前為止我們就可以使用Shiro進(jìn)行應(yīng)用程序的安全控制了,但是還是缺少如對(duì)Web驗(yàn)證、Java方法驗(yàn)證等的一些簡(jiǎn)化實(shí)現(xiàn)。 ? ?

    ?

    示例源代碼:https://github.com/zhangkaitao/shiro-example;

    總結(jié)

    以上是生活随笔為你收集整理的Realm及相关对象——《跟我学Shiro》的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。