权限拦截如何实现

本文介绍了一种基于五张表(用户、角色、用户角色、权限、角色权限)的权限拦截器实现方法,详细讲解了如何在Spring MVC框架下配置权限拦截器,包括获取系统和用户权限、判断请求是否需要权限控制及用户是否有权限的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先我们先来梳理一下

	实现权限拦截需要五张表分别是:用户表,角色表,用户角色表,权限表,角色权限表。
	这五张表的关系是:用户和角色是多对多,角色和权限是多对多。
	权限拦截是拦截的什么呢? 如果你给这个用户赋予了权限,这个则不需要拦截。所以拦截的是用户的权限。
	小小的梳理之后,我们就开始说如何实现。

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("您没有该权限!")
  	}
     }    
});

权限拦截到此结束,小编写的不是很好 术语不专业 有错误的地方希望大家一定要告诉我哈!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值