权限拦截
思路解析
一.阅读本篇之前,可以先提前了解小编在之前写过的登录拦截的那篇博客。有助于更好的理解本篇权限拦截。
二.权限拦截思路解析:获取用户访问路径uri
1.首先遍历所有的权限判断其中是否包含该uri,如果不包含则不需要拦截(比如:userController/login )比如这个登录方法的路径访问时就不需要拦截,即我们只拦截所有权限里的路径,因此在数据库编写路权限径时注意区分大小写,及不能漏掉要拦截的权限路径。如果包含则需要判断该用户是否有对应权限。
2.当所有的权限包含该uri时,判断该用户的权限列表是否有对应权限。如有则说明该用户访问的路径他有权利去访问和之后的相关操作,不需要拦截。如果用户权限列表没有该uri说明用户不具备此权限,需要拦截该用户。
3.当需要拦截该用户时,就和登录拦截很相似,需要判断是不是ajax请求并返回相应提示信息给用户。
准备工作
如上所述,权限拦截需要如下“工具”:
1.permissionListAll 所有的权限列表
public List<Permission> queryPermissionList() {
return permissionRepository.findAll();
}
通过JpaRepository接口自带的查询方法查出所有权限列表。
2.permissionListByUserId 用户的权限列表
@Query(nativeQuery = true,value = "select DISTINCT tp.* FROM t_user_role_new tur LEFT JOIN t_role_permission_new trp ON tur.roleId = trp.roleId LEFT JOIN t_permission_new tp on trp.permissionId = tp.id where tur.userId = ?1")
List<Permission> findPermissionListByUserId(Integer userId);
为了提高性能小编是通过三表联查获得用户权限:通过用户id查询,用户_角色关联表左联角色_权限关联表左联权限表,通过三表联查查询到该用户id对应的所有权限。
3.String uri = request.getRequestURI(); 用户访问的地址栏路径。(URI,统一资源标志符(Uniform Resource Identifier, URI),表示的是web上每一种可用的资源,如 HTML文档、图像、视频片段、程序等都由一个URI进行定位的。)
具体实现
新建一个PermissionInterceptor基础HandlerInterceptorAdapter并重写preHandle方法。
package com.fh.interceptor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.fh.model.Permission;
import com.fh.util.JsonUtil;
public class PermissionInterceptor extends HandlerInterceptorAdapter{
@SuppressWarnings("unchecked")
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
HttpSession session = request.getSession();
/*
* 登陆成功后login方法已经将permissionListByUserId,
* permissionListAll放入session里,所以我们只需要从session中取出即可
*/
List<Permission> permissionListByUserId = (List<Permission>) session.getAttribute("permissionListByUserId");
List<Permission> permissionListAll = (List<Permission>) session.getAttribute("permissionListAll");
String uri = request.getRequestURI();// 类似于userController/addUser
if(StringUtils.isBlank(uri)) {//如果uri为空则不需要拦截
return true;
}
boolean contains = false;
/*
* 立一个flag(contains) 若flag(contains)为true表明所有权限包含该uri,
* 一旦包含即可break提高代码性能。
*/
if(permissionListAll != null && permissionListAll.size() > 0) {
for (Permission permission : permissionListAll) {
if(StringUtils.isNotBlank(permission.getUrl()) && uri.contains(permission.getUrl())) {
contains = true;
break;
}
}
}
if(contains == false) {//若flag(contains)为false表明所有权限列表如果不包含则不需要拦截
return true;
}else {//表明所有权限permissionListAll包含该uri,就需要进一步验证用户权限是否包含
boolean hasPermission = false;
/*
* 当所有的权限包含该uri时,判断该用户的权限列表是否有对应权限。
* 如有则说明该用户访问的路径他有权利去访问和之后的相关操作,不需要拦截。
* 如果用户权限列表没有该uri说明用户不具备此权限,需要拦截该用户。
*
*/
if(permissionListByUserId != null && permissionListByUserId.size() > 0) {
for (Permission permission : permissionListByUserId) {
if(StringUtils.isNotBlank(permission.getUrl()) && uri.contains(permission.getUrl())) {
hasPermission = true;
break;
}
}
}
if(hasPermission == true) {//在permissionListAll里边,且有用户权限。允许用户访问。
return true;
}else {//用户权限列表没有该uri说明用户不具备此权限,需要拦截该用户
String header = request.getHeader("X-Requested-With");
//根据请求头部判断是不是ajax请求
if(StringUtils.isNotBlank(header) && header.equals("XMLHttpRequest")) {
//是ajax请求就要给前端页面一个信号,在前端页面判断后可以再弹出提示信息,跳到指定页面
Map<String, Object> result = new HashMap<String, Object>();
result.put("code", 2000);
JsonUtil.outJson(response, result);
}else {//不是ajax请求可以直接重定向到指定页面
response.sendRedirect(request.getServletContext().getContextPath()+"/no-permission.jsp");
}
return false;
}
}
}
}
springMVC.xml配置
<mvc:interceptor>
<mvc:mapping path="/**" />
/*
*配置白名单,放开静态资源
*/
<mvc:exclude-mapping path="/js/**" />
<mvc:exclude-mapping path="/bootstrap/**" />
<bean class="com.fh.interceptor.PermissionInterceptor"></bean>
</mvc:interceptor>
写在最后
本篇为小编和人理解所作,如有错误请联系小编进行修改或删除。