一、前言
在Shiro的官方文檔中,默認介紹的是與JSP整合來做頁面上的權限控制,Shiro有一套自己的標籤庫,能與JSP無縫整合,只需要在JSP頁面上引入Shiro的標籤庫即可
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
但是越來越多的WEB應用已經慢慢棄用JSP,改成用HTML(因爲HTML比JSP快呀),但是在HTML中,就不能使用Shiro默認的標籤庫,那是否有可替代的標籤庫呢?當然了,thymeleaf就可以在HTML中使用,thymeleaf可以輕鬆自如的自定義標籤並配合權限控制網頁上的組件顯示與否
二、引入thymeleaf
引入thymeleaf,分爲3步
1、在pom.xml文件中引入thymeleaf相關Jar包
<!-- thymeleaf包 -->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>3.0.9.RELEASE</version>
</dependency>
2、在spring-servlet.xml文件中起用thymeleaf模板引擎
<!--viewResolver-->
<bean id="viewResolver" class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
<property name="order" value="1"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine" ref="templateEngine"/>
</bean>
<!-- templateEngine -->
<bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver"/>
<property name="enableSpringELCompiler" value="true" />
<property name="additionalDialects">
<set>
<bean class="at.pollux.thymeleaf.shiro.dialect.ShiroDialect"/>
</set>
</property>
</bean>
<bean id="templateResolver" class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/html/"/>
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML"/>
<property name="characterEncoding" value="UTF-8"/>
</bean>
因爲我使用的是Spring MVC,在web.xml文件中,配置了DispatcherServlet會攔截所有請求,包括靜態資源如html,css,js等,因此需要在spring-servlet.xml文件中指定靜態資源文件路徑,才能訪問到靜態資源
<!-- 靜態資源 -->
<mvc:resources location="/WEB-INF/js/" mapping="/js/**"/>
<mvc:resources location="/WEB-INF/css/" mapping="/css/**"/>
<mvc:resources location="/WEB-INF/image/" mapping="/image/**"/>
<mvc:resources location="/html/" mapping="/html/**"/>
3、在html中引入thymeleaf的標籤庫
<html xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
三、驗證
在測試之前,先介紹幾個重要的標籤
shiro:guest:判斷是否是未登錄,即遊客
shiro:hasRole:判斷是否有xxx角色
shiro:hasPermission:判斷是否有xxx權限
shiro:hasAnyRoles:判斷是否有任何一個指定的權限
1、在/html/user/目錄下新增userManager.html文件,內容如下
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<p shiro:guest=""><a href="../login.html">遊客訪問,請登錄</a></p>
<p shiro:hasRole="USER"> 有 USER 角色權限</p>
<button shiro:hasPermission="USER:DELETE" type="button">刪除用戶</button>
<button shiro:hasPermission="USER:CREATE" type="button">新增用戶</button>
<div shiro:hasAnyRoles="SALES,USER"><li><a href="javascript:;" id="shouhuo">用戶管理</a></li></div>
</body>
</html>
2、在UserController中增加對外訪問服務userManager
@RequestMapping(value="/userManager",method = RequestMethod.GET)
public String userManager() {
return "user/userManager";
}
3、在自定義的UserShiroRealm的doGetAuthorizationInfo方法中,配置用戶有USER角色及USER:DELETE權限
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String username = (String)principals.getPrimaryPrincipal();
if(username == null) {
throw new BugException("未登錄");
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
Set<String> roles = new HashSet<String>();
Set<String> stringPermissions = new HashSet<String>();
roles.add("USER");
stringPermissions.add("USER:DELETE");//角色:刪除權限
info.setRoles(roles);
info.setStringPermissions(stringPermissions);
return info;
}
未登錄,直接訪問http://localhost:8080/bug.web/user/userManager,頁面顯示遊客訪問,請登錄
登錄後再次訪問http://localhost:8080/bug.web/user/userManager,頁面顯示如下
shiro:hasRole:因爲用USER角色,所以“有 USER 角色權限”顯示了
shiro:hasPermission:
因爲沒有USER:CREATE權限,所以“新增用戶”按鈕未顯示
因爲有USER:DELETE權限,所以“刪除用戶”按鈕顯示
shiro:hasAnyRoles:雖然沒有SALES角色,但是有USER角色,所以“用戶管理”顯示
從以上結果可看出,通過與thymeleaf的整合,在HTML頁面上也可以做細粒度的權限控制,可以很方便我們按鈕哪些按鈕需要顯示,哪些按鈕不顯示
四、問題
上面我是訪問Controller層,Spring自動找到需要渲染的html頁面返回給用戶,但是在大部分項目中,是先訪問HTML,然後通過ajax方式請求後臺獲得數據渲染到頁面上,問題來了,通過先訪問HTML的方式,在HTML中配置的shiro標籤就不生效了,暫時未找到好的方法解決,如果你有好的解決方案,歡迎留言討論,謝謝!!!