一、前言
在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标签就不生效了,暂时未找到好的方法解决,如果你有好的解决方案,欢迎留言讨论,谢谢!!!