1配置文件,(*.ini,*,xml ,或者配置類)后面細(xì)講
一,登陸,登出過程
1伤柄,根據(jù)配置文件,生成SecurityManager工廠???Factory<org.apache.shiro.mgt.SecurityManager>?factory?= new?IniSecurityManagerFactory("classpath:shiro.ini");??
2文搂,從工廠中獲取SecurityManager實(shí)例
org.apache.shiro.mgt.SecurityManager?securityManager?=?factory.getInstance();??
3适刀,把實(shí)例綁定到SecurityUtils
?SecurityUtils.setSecurityManager(securityManager);??
4,獲取Subject對象煤蹭,Subject subject=SecurityUtils.getSubject();
5笔喉,獲取登陸token,UsernamePasswordToken?token?=new?UsernamePasswordToken("zhang",?"123");??
6,subject.login(token);
7疯兼,subject.logout();
二然遏,login()方法流程
流程如下:
1贫途、首先調(diào)用Subject.login(token)進(jìn)行登錄吧彪,其會自動(dòng)委托給Security Manager,調(diào)用之前必須通過SecurityUtils. setSecurityManager()設(shè)置丢早;
2姨裸、SecurityManager負(fù)責(zé)真正的身份驗(yàn)證邏輯秧倾;它會委托給Authenticator進(jìn)行身份驗(yàn)證;
3傀缩、Authenticator才是真正的身份驗(yàn)證者那先,Shiro API中核心的身份認(rèn)證入口點(diǎn),此處可以自定義插入自己的實(shí)現(xiàn)赡艰;
4售淡、Authenticator可能會委托給相應(yīng)的AuthenticationStrategy進(jìn)行多Realm身份驗(yàn)證,默認(rèn)ModularRealmAuthenticator會調(diào)用AuthenticationStrategy進(jìn)行多Realm身份驗(yàn)證慷垮;
5揖闸、Authenticator會把相應(yīng)的token傳入Realm,從Realm獲取身份驗(yàn)證信息料身,如果沒有返回/拋出異常表示身份驗(yàn)證失敗了汤纸。此處可以配置多個(gè)Realm,將按照相應(yīng)的順序及策略進(jìn)行訪問芹血。
三贮泞,Realm
可以理解為,用哪的數(shù)據(jù)(用數(shù)據(jù)庫的數(shù)據(jù)幔烛,內(nèi)存的啃擦,或者其他地方的數(shù)據(jù)),驗(yàn)證登陸的方法(具體的驗(yàn)證實(shí)現(xiàn))
org.apache.shiro.realm.Realm接口如下: 有3個(gè)方法
String?getName();?//返回一個(gè)唯一的Realm名字??
boolean?supports(AuthenticationToken?token);?//判斷此Realm是否支持此Token??
AuthenticationInfo?getAuthenticationInfo(AuthenticationToken?token)? (驗(yàn)證的邏輯说贝,根據(jù)自己的情況重寫)
throws?AuthenticationException;??//根據(jù)Token獲取認(rèn)證信息??
public?class?MyRealm1?implements?Realm?{??
@Override??
public?String?getName()?{??
return?"myrealm1";??
????}??
@Override??
public?boolean?supports(AuthenticationToken?token)?{??
//僅支持UsernamePasswordToken類型的Token??
return?token?instanceof?UsernamePasswordToken;???
????}??
@Override??
public?AuthenticationInfo?getAuthenticationInfo(AuthenticationToken?token)?throws?AuthenticationException?{??
String?username?=?(String)token.getPrincipal();//得到用戶名??
String?password?=new?String((char[])token.getCredentials());?//得到密碼??
if(!"zhang".equals(username))?{??
throw?new?UnknownAccountException();?//如果用戶名錯(cuò)誤??
????????}??
if(!"123".equals(password))?{??
throw?new?IncorrectCredentialsException();?//如果密碼錯(cuò)誤??
????????}??
//如果身份認(rèn)證驗(yàn)證成功议惰,返回一個(gè)AuthenticationInfo實(shí)現(xiàn);??
return?new?SimpleAuthenticationInfo(username,?password,?getName());??
????}??
}? ?
在配置文件中配置用那個(gè)Realm類
#聲明一個(gè)realm??
myRealm1=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm1??
#指定securityManager的realms實(shí)現(xiàn)??
securityManager.realms=$myRealm1???
也可以配置多個(gè)Realm
#聲明一個(gè)realm??
myRealm1=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm1??
myRealm2=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm2??
#指定securityManager的realms實(shí)現(xiàn)??
securityManager.realms=$myRealm1,$myRealm2???
SecurityManager會按照Realm得順序去驗(yàn)證乡恕,此處我們使用顯示指定順序的方式指定了Realm的順序言询,如果刪除“securityManager.realms=$myRealm1,$myRealm2”,那么securityManager會按照realm聲明的順序進(jìn)行使用(即無需設(shè)置realms屬性傲宜,其會自動(dòng)發(fā)現(xiàn))运杭,當(dāng)我們顯示指定realm后,其他沒有指定realm將被忽略函卒,如“securityManager.realms=$myRealm1”辆憔,那么myRealm2不會被自動(dòng)設(shè)置進(jìn)去。
Shiro默認(rèn)提供的Realm
以后一般繼承AuthorizingRealm(授權(quán))即可报嵌;其繼承了AuthenticatingRealm(即身份驗(yàn)證)虱咧,而且也間接繼承了CachingRealm(帶有緩存實(shí)現(xiàn))。其中主要默認(rèn)實(shí)現(xiàn)如下:
org.apache.shiro.realm.text.IniRealm:[users]部分指定用戶名/密碼及其角色锚国;[roles]部分指定角色即權(quán)限信息腕巡;
org.apache.shiro.realm.text.PropertiesRealm:?user.username=password,role1,role2指定用戶名/密碼及其角色;role.role1=permission1,permission2指定角色及權(quán)限信息血筑;
org.apache.shiro.realm.jdbc.JdbcRealm:通過sql查詢相應(yīng)的信息绘沉,如“select password from users where username = ?”獲取用戶密碼煎楣,“select password, password_salt from users where username = ?”獲取用戶密碼及鹽;“select role_name from user_roles where username = ?”獲取用戶角色车伞;“select permission from roles_permissions where role_name = ?”獲取角色對應(yīng)的權(quán)限信息择懂;也可以調(diào)用相應(yīng)的api進(jìn)行自定義sql;
上面說的是幾種Realm類型另玖,一般我們重寫的時(shí)候困曙,繼承AuthorizingRealm就可以了,重寫里面的方法谦去,現(xiàn)在一般是從方法赂弓,或者接口取用戶信息
JDBC Realm使用
1,Maven添加數(shù)據(jù)驅(qū)動(dòng)引用
2哪轿,在配置文件里配飾數(shù)據(jù)庫配置 盈魁,(shiro-jdbc-realm.ini)?
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm??
dataSource=com.alibaba.druid.pool.DruidDataSource??
dataSource.driverClassName=com.mysql.jdbc.Driver??
dataSource.url=jdbc:mysql://localhost:3306/shiro??
dataSource.username=root??
#dataSource.password=??
jdbcRealm.dataSource=$dataSource??
securityManager.realms=$jdbcRealm???
1、變量名=全限定類名會自動(dòng)創(chuàng)建一個(gè)類實(shí)例
2窃诉、變量名.屬性=值?自動(dòng)調(diào)用相應(yīng)的setter方法進(jìn)行賦值
3杨耙、$變量名?引用之前的一個(gè)對象實(shí)例
2.6?Authenticator及AuthenticationStrategy
Authenticator的職責(zé)是驗(yàn)證用戶帳號,是Shiro API中身份驗(yàn)證核心的入口點(diǎn):?
public?AuthenticationInfo?authenticate(AuthenticationToken?authenticationToken)??
throws?AuthenticationException;???
如果驗(yàn)證成功飘痛,將返回AuthenticationInfo驗(yàn)證信息珊膜;此信息中包含了身份及憑證;如果驗(yàn)證失敗將拋出相應(yīng)的AuthenticationException實(shí)現(xiàn)宣脉。
SecurityManager接口繼承了Authenticator车柠,另外還有一個(gè)ModularRealmAuthenticator(Authenticator接口的實(shí)現(xiàn)類)實(shí)現(xiàn),其委托給多個(gè)Realm進(jìn)行驗(yàn)證塑猖,驗(yàn)證規(guī)則通過AuthenticationStrategy接口指定竹祷,默認(rèn)提供的實(shí)現(xiàn):
FirstSuccessfulStrategy:只要有一個(gè)Realm驗(yàn)證成功即可,只返回第一個(gè)Realm身份驗(yàn)證成功的認(rèn)證信息羊苟,其他的忽略塑陵;
AtLeastOneSuccessfulStrategy:只要有一個(gè)Realm驗(yàn)證成功即可,和FirstSuccessfulStrategy不同蜡励,返回所有Realm身份驗(yàn)證成功的認(rèn)證信息令花;
AllSuccessfulStrategy:所有Realm驗(yàn)證成功才算成功,且返回所有Realm身份驗(yàn)證成功的認(rèn)證信息凉倚,如果有一個(gè)失敗就失敗了兼都。
配置文件中,指定?authenticator實(shí)現(xiàn)稽寒,還有指定驗(yàn)證策略(authenticationStrategy)
#指定securityManager的authenticator實(shí)現(xiàn)??
authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator??
securityManager.authenticator=$authenticator??
#指定securityManager.authenticator的authenticationStrategy??
allSuccessfulStrategy=org.apache.shiro.authc.pam.AllSuccessfulStrategy??
securityManager.authenticator.authenticationStrategy=$allSuccessfulStrategy??
配置Realm扮碧,只用了1,2
.myRealm1=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm1??
myRealm2=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm2??
myRealm3=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm3??
securityManager.realms=$myRealm1,$myRealm3??
注意:如果有多個(gè)認(rèn)證Realm需要配置authenticationStrategy??