項(xiàng)目簡介
springboot中使用shiro大都是通過shiro-spring.jar進(jìn)行的整合的,雖然不是太復(fù)雜,但是也無法做到spring-boot-starter風(fēng)格的開箱即用。
項(xiàng)目中經(jīng)常用到的功能比如:驗(yàn)證碼很钓、密碼錯(cuò)誤次數(shù)限制苹享、賬號(hào)唯一用戶登陸公罕、動(dòng)態(tài)URL過濾規(guī)則身堡、無狀態(tài)鑒權(quán)等等们童,shiro還沒有直接提供支持侯养。
jsets-shiro-spring-boot-starter對(duì)這些常用的功能進(jìn)行了封裝和自動(dòng)導(dǎo)入敦跌,少量的配置就可以應(yīng)用在項(xiàng)目中。
1逛揩、項(xiàng)目地址:jsets-shiro-spring-boot-starter
2柠傍、使用說明:使用說明
3、示例應(yīng)用:jsets-shiro-demo
如果您對(duì)這個(gè)組件感興趣請(qǐng)star收藏辩稽,在使用這個(gè)組件中有任何問題或意見都可以在這里交流惧笛,歡迎提交代碼。
已完成功能
1搂誉、spring-boot-starter風(fēng)格的開箱即用徐紧。
2、區(qū)分ajax請(qǐng)求和普通請(qǐng)求炭懊,普通請(qǐng)求通過跳轉(zhuǎn)來響應(yīng)未登陸和未授權(quán)并级,AJAX請(qǐng)求通過狀態(tài)碼和消息響應(yīng)未登陸和未授權(quán)。
3侮腹、集成jcaptcha驗(yàn)證碼嘲碧。
4、密碼輸入錯(cuò)誤父阻,重試次數(shù)限制愈涩。
5望抽、賬號(hào)唯一用戶登陸,一個(gè)賬號(hào)只允許一個(gè)用戶登陸履婉。
6煤篙、與SpringCache無縫對(duì)接,支持guava毁腿、ehcache辑奈、redis等。
7已烤、提供認(rèn)證\授權(quán)緩存數(shù)據(jù)同步接口鸠窗,即時(shí)生效。
8胯究、支持動(dòng)態(tài)URL過濾規(guī)則稍计。
9、無狀態(tài)認(rèn)證授權(quán)支持裕循,共存有狀態(tài)和無狀態(tài)兩種鑒權(quán)方式臣嚣,無狀態(tài)鑒權(quán)支持JWT(JSON WEB TOKEN)、HMAC(哈希消息認(rèn)證碼)兩種協(xié)議剥哑。
10茧球、在線session管理,強(qiáng)制用戶下線功能星持。
后續(xù)計(jì)劃功能
1、cas單點(diǎn)登陸集成
2弹灭、oauth2.0支持
快速體驗(yàn)
1督暂、pom.xml中添加:
<dependency>
<groupId>org.jsets</groupId>
<artifactId>jsets-shiro-spring-boot-starter</artifactId>
<version>0.0.1</version>
</dependency>
2、application.properties添加下面配置:
###jsets-shiro配置
#登陸頁面
jsets.shiro.login-url=/login
#登陸成功頁面
jsets.shiro.login-success-url=/index
#忽略攔截的URL,靜態(tài)資源
jsets.shiro.filte-rules[0]=/assets/**-->anon
#登陸
jsets.shiro.filte-rules[1]=/login/**-->authc
#退出
jsets.shiro.filte-rules[2]=/logout/**-->logout
#所有路徑穷吮,斷言session中存在用戶
jsets.shiro.filte-rules[3]=/**-->user
3逻翁、創(chuàng)建Controller類IndexAction.java:
@Controller
public class IndexAction {
@RequestMapping("/")
public String def() {
return "index";
}
@RequestMapping("/index")
public String index() {
return "index";
}
@RequestMapping("/login")
public String login() {
return "login";
}
}
4、創(chuàng)建登陸頁面login.html:
<form class="login-form" action="${ctx}/login" method="post">
<div class="form-item">
用戶名:<input type="text" name="username" />
</div>
<div class="form-item">
密碼:<input type="password" name="password" />
</div>
<div class="form-item">
<button type="submit">登錄</button>
</div>
</form>
<!-- 認(rèn)證信息 -->
<font color="red">${Request["shiro_auth_message"]!}</font>
5捡鱼、創(chuàng)建主頁index.html:
<div class="body">
歡迎您:${Session.shiro_current_user.account!}
<br>
退出:<a href="${ctx}/logout">退了</a>
</div>
6八回、啟用jsets-shiro-spring-boot-starter:
@SpringBootApplication
@EnableJsetsShiro
public class Application{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
啟動(dòng)springboot應(yīng)用坯辩,控制臺(tái)會(huì)打印出組件預(yù)置的體驗(yàn)賬號(hào)和密碼:
使用這個(gè)賬號(hào)和密碼就可以登陸系統(tǒng)了不恭。
鑒權(quán)要素
鑒:認(rèn)證(Authentication)即證明您是賬號(hào)表示的那個(gè)人,基于form的認(rèn)證中使用口令(密碼)钉寝,rest api認(rèn)證中使用令牌(token)乍迄。
權(quán):權(quán)限驗(yàn)證(Authorization)即根據(jù)一個(gè)判斷規(guī)則來驗(yàn)證您是否能執(zhí)行一個(gè)操作管引。
認(rèn)證的過程需要賬號(hào)數(shù)據(jù),這個(gè)數(shù)據(jù)至少包含三個(gè)元素:賬號(hào)(用戶名)闯两、密碼褥伴、賬號(hào)是否可用谅将。
jsets-shiro-spring-boot-starter中使用Account接口表示賬號(hào)數(shù)據(jù)、使用ShiroAccountProvider接口為鑒權(quán)操作提供Account數(shù)據(jù)重慢,數(shù)據(jù)來源不限比如可以從數(shù)據(jù)庫饥臂、文件、LDAP似踱、遠(yuǎn)程服務(wù)等各種方式加載隅熙。
權(quán)限驗(yàn)證的過程需要權(quán)限數(shù)據(jù)和規(guī)則數(shù)據(jù),權(quán)限泛指能否操作資源屯援,角色是權(quán)限的集合猛们,如果使用權(quán)限來表示一個(gè)用戶能操作的資源顯然不方便,所以大部分系統(tǒng)的安全模型都是基于RBAC(Role-Based Access Control 基于角色的權(quán)限訪問控制)的狞洋。jsets-shiro-spring-boot-starter同樣使用ShiroAccountProvider接口為鑒權(quán)操作提供權(quán)限(角色)數(shù)據(jù)弯淘,數(shù)據(jù)來源不限。
具體參見"使用說明--接入用戶數(shù)據(jù)"一章吉懊。
規(guī)則數(shù)據(jù)庐橙,如果沒有規(guī)則就不存在判斷,權(quán)限驗(yàn)證也就無從談起借嗽,在shiro中規(guī)則表示成這樣:
article/update=roles[role_editor]
article/delete=roles[role_chief]
article/publish=roles[role_chief]
"article/update"就是操作的資源态鳖,"roles[role_editor]"是判斷標(biāo)準(zhǔn),表示用戶的角色列表中包含"role_editor"角色恶导,操作加上判斷標(biāo)準(zhǔn)就是規(guī)則浆竭。jsets-shiro-spring-boot-starter中您可以在application.properties中配置這樣的規(guī)則。也可以通過shiro的AOP方式配置規(guī)則惨寿,類似于這樣:
@RequiresRoles("role_editor")
public void update(Article article){
}
這兩種方式是有局限的邦泄,比如角色-資源的對(duì)應(yīng)關(guān)系發(fā)生變更,比如新增了一種角色裂垦,那就只能修改配置或者代碼然后重啟動(dòng)系統(tǒng)才能使得這些變更生效顺囊。實(shí)際開發(fā)中則更希望通數(shù)據(jù)庫查詢出角色-資源的對(duì)應(yīng)數(shù)據(jù),動(dòng)態(tài)生成URL規(guī)則蕉拢,當(dāng)角色-資源的對(duì)應(yīng)關(guān)系發(fā)生變更時(shí)能刷新并立即用戶這些規(guī)則特碳。
您可以通過ShiroFilteRulesProvider接口為鑒權(quán)操作提供規(guī)則數(shù)據(jù),并且支持實(shí)時(shí)刷新應(yīng)用這些規(guī)則晕换。
具體參見"使用說明--動(dòng)態(tài)URL過濾"一章午乓。
無狀態(tài)鑒權(quán)
無狀態(tài)(Stateless)鑒權(quán)通常應(yīng)用在微服務(wù)(REST API)架構(gòu)中,使用數(shù)字摘要(簽名)技術(shù)生成一個(gè)token作為認(rèn)證和授權(quán)的憑證闸准,整個(gè)認(rèn)證和授權(quán)過程不依賴于cookie或session硅瞧,服務(wù)端不保留客戶端狀態(tài)因此每次請(qǐng)求都要攜帶這個(gè)token。
jsets-shiro-spring-boot-starter提供兩種無狀態(tài)鑒權(quán)方式恕汇,分別是散列消息認(rèn)證碼(HMAC)腕唧、JSON WEB TOKEN(JWT)或辖。
HMAC適合端到端的鑒權(quán),即客戶端拿著簽名讓服務(wù)端進(jìn)行驗(yàn)簽枣接。
JWT適合客戶端詢問系統(tǒng)B是否有權(quán)訪問系統(tǒng)C和系統(tǒng)N如果有請(qǐng)開份憑證颂暇,然后拿著憑證讓系統(tǒng)C和系統(tǒng)N進(jìn)行驗(yàn)簽。
JWT是自包含的但惶,令牌中攜帶訪問主張(角色或權(quán)限)耳鸯,所以JWT鑒權(quán)不需要查詢數(shù)據(jù)。HMAC鑒權(quán)則需要查詢數(shù)據(jù)庫獲取角色或權(quán)限數(shù)據(jù)膀曾。HMAC和JWT鑒權(quán)過程均不產(chǎn)生session县爬。
如果您的系統(tǒng)即有狀態(tài)鑒權(quán)(即基于FORM的登陸認(rèn)證)又有無狀態(tài)鑒權(quán)(即提供rest接口),畢竟不是所有的系統(tǒng)都做了服務(wù)化拆分的添谊,默認(rèn)情況下HMAC也是使用ShiroAccountProvider接口為鑒權(quán)操作提供身份認(rèn)證和權(quán)限驗(yàn)證數(shù)據(jù)财喳,和有狀態(tài)鑒權(quán)公用一套數(shù)據(jù)。如您想拆分它們斩狱,即HMAC使用自己的鑒權(quán)數(shù)據(jù)耳高,可以使用ShiroStatelessAccountProvider為無狀態(tài)鑒權(quán)提供數(shù)據(jù)。
具體參見"使用說明--無狀態(tài)鑒權(quán)"一章所踊。
組件擴(kuò)展
JsetsShiroConfigurationAdapter是shiro配置的適配器泌枪,通過它您可以定制Realm、filter秕岛、SessionDAO碌燕、CacheManager等。
示例展示
jsets-shiro-demo是jsets-shiro-spring-boot-starter是應(yīng)用示例继薛,做的不是很精細(xì)陆蟆,主要為了演示功能實(shí)現(xiàn)。
主界面:
驗(yàn)證碼:
用戶被踢出:
密碼輸入錯(cuò)誤重試次數(shù)限制:
角色列表:
權(quán)限攔截:
資源分配:
權(quán)限驗(yàn)證通過:
HMAC驗(yàn)簽通過:
HMAC簽名失效:
HMAC簽名無效:
JWT權(quán)限驗(yàn)證失敗:
JWT需要身份認(rèn)證:
在線用戶列表:
強(qiáng)制用戶下線:
更多功能和特性請(qǐng)參見jsets-shiro-spring-boot-starter源碼和使用說明惋增。