首先我们先来梳理一下
实现权限拦截需要五张表分别是:用户表,角色表,用户角色表,权限表,角色权限表。
这五张表的关系是:用户和角色是多对多,角色和权限是多对多。
权限拦截是拦截的什么呢? 如果你给这个用户赋予了权限,这个则不需要拦截。所以拦截的是用户的权限。
小小的梳理之后,我们就开始说如何实现。
1.首先我们在controller的登录方法(login)里获取系统的所有权限,这时候我们需要一个常量类来封装一些公共的东西
class SessionKey{
public static final String PERMISSION_ALL_LIST= "permissionAllList";
}
并把它放到session中
List<Permission> permissionAllList = permissionService.PermissionList();
session.setAttribute(Const.SessionKey.PERMISSION_ALL_LIST, permissionAllList);
2.获取了系统的所有权限了,接下来我们获取用户的所有权限。
我们可以通过当前登录用户的id去用户角色关系表里查出该用户所拥有的所有角色id,
然后可以通过这些角色id去角色权限关系表中查出这些角色id对应的权限id,
然后再通过这些权限id去权限表里进行查询就可以获取当前登录用户的所有权限了。
在PermissionRepository接口里边定义一个方法public ListfindPermissionListByUserId(Integer userId);
在其方法上使用@Query注解,在其注解里边写一个三表联查的sql语句查询到用户的所有权限
然后在PermissionService的接口里边定义方法List findPermissionListByUserId(Integer userId);并在impl实现这个方法
回到controller层这时候我们就可以调用PermissionService里边的findPermissionListByUserId的方法了,获取完用户的所有权限,当然
也要把它放到session中
class SessionKey{
//系统的所有权限
public static final String PERMISSION_ALL_LIST= "permissionAllList";
//用户的所有权限
public static final String PERMISSION_USER_LIST ="permissionUserList";
}
//获取用户的所有权限
List<Permission> permissionUserList = permissionService.findPermissionListByUserId(user.getUserId());
session.setAttribute(Const.SessionKey.PERMISSION_USER_LIST, permissionUserList);
3.在springMVC.xml中配置权限拦截器
<!-- 注册拦截器 -->
<mvc:interceptors>
-- 权限拦截器 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
-- 白名单路径 -->
<mvc:exclude-mapping path="/user/login"/>
<mvc:exclude-mapping path="/js/**"/>
<mvc:exclude-mapping path="/bootstrap/**"/>
-- 拦截器路径 -->
<bean class="com.fh.interceptor.PermissionInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
4.根据在springMVC.xml中配置的拦截器路径创建拦截器类PermissionInterceptor,并继承 HandlerInterceptorAdapter
重写它的preHandle方法
1.获取资源匹配符String requestURI = request.getRequestURI();并判断不等于空,说明什么也没请求,直接放过。
这时候我们要区分一下URL和URI
URL(资源【定位】符): 【http://localhost:8080】/movie_admin_new/userController/toUserList
URI(资源匹配符): /movie_admin_new/userController/toUserList 这个也就是我们在Permission表中的url路径
2…判断请求的uri是否需要权限控制,在数据库permission表中的url需要控制
(1)获取系统的所有权限集合,怎么获取呢 当然是从session中拿,因为我们在做登录的时候已经把获取到的系统权限和用户权限都
放到了session中, for循坏遍历所有权限集合permissionAllList。
(2)String url = permission.getUrl();获取了permission表中的所有url,
这时候去判断如果requestURI.contains(url) (contains 这个是包含的意思)如果for循环全部走完,requestURI包含url
则需要控制,
List<Permission> permissionAllList = (List<Permission>) request.getSession().getAttribute(Const.SessionKey.PERMISSION_ALL_LIST);
boolean needControl = false;
for (Permission permission : permissionAllList) {
//用户请求的uri是否包含需要控制的权限的uri
//contains 包含permission.getUrl()
String url = permission.getUrl();
if(StringUtils.isNotBlank(url) && requestURI.contains(url)){
needControl = true;
break;
}
}
beeak是跳出循环
3.用户请求的uri不需要权限控制,则放过该请求。
if(!needControl){
return true;
}
!needControl:needControl=false !是不等于
4.判断用户是否有权限 这个跟判断请求的uri是否需要权限控制是同理的
(1)首先我们肯定要先获取用户的所有权限,获取完之后for循坏遍历它
(2)获取permission的url String permissionUrl = permission.getUrl();
(3)使用StringUtils.isNotBlank判断permissionUrl 不等于和字符串,并且&& requestURI是否包含了permissionUrl 。
(4)没有包含则用户没有此权限的路径
List<Permission> permissionUserList = (List<Permission>) request.getSession().getAttribute(Const.SessionKey.PERMISSION_USER_LIST);
boolean hasPermission = false;
for (Permission permission : permissionUserList) {
/*
* requestURI = /movie_admin_new/userController/toUserList
* permissionUrl = userController/toUserList
*/
String permissionUrl = permission.getUrl();
if(StringUtils.isNotBlank(permissionUrl) && requestURI.contains(permissionUrl)){
hasPermission = true;
break;
}
}
break 跳出循环
(5)判断用户是否有权限
if(hasPermission){
//用户有权限
return true;
}
5.接下来判断用户没有权限的逻辑
String xrwHeader = request.getHeader("X-Requested-With");
if(StringUtils.isNotBlank(xrwHeader) && xrwHeader.equals("XMLHttpRequest")){
//是ajax请求,返回相应的状态码,让前端做处理
Map<String, Object> map = MyUtils.getMap();
map.put("code", "110");
JsonUtil.outJson(response, map);
//记录非法请求信息
return false;
}else{
//不是ajax请求,跳转到没有权限页面
String contextPath = request.getServletContext().getContextPath();
response.sendRedirect(contextPath + "/no_permission.jsp");
//记录非法请求信息
return false;
}
6.在前台jsp页面写一个jquery的ajax请求全局设置
$.ajaxSetup({
//在ajax成功回调函数或失败回调函数被调用都会调用这个函数
/*
为什么需要判断请求是ajax请求
1.判断之后,ajax请求被拦截后,可以在前端根据返回的json数据做多种处理,可以满足多种需求
*/
complete:function(request){
if(request.responseJSON.code == 12345){
//如果返回的code==12345,说明用户未登录
alert("用户没有登录,或者登录超时,即将跳转到登录界面!")
location.href = "<%=request.getContextPath()%>/login.jsp";
}else if(request.responseJSON.code == 110){
alert("您没有该权限!")
}
}
});
权限拦截到此结束,小编写的不是很好 术语不专业 有错误的地方希望大家一定要告诉我哈!