基于RBAC用户权限控制的校验

本文介绍了基于RBAC的用户权限控制,通过用户登录后将权限存入缓存,利用拦截器对每个请求进行权限校验。详细步骤包括:配置拦截器、实现缓存、编写拦截器代码以及用户登录后的权限存储操作。

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

在上一次的文章中,简单的说明了基于RBAC用户权限控制的菜单显示和表结构的设计,而往往在企业项目中,仅仅控制用户菜单是不够的,而是要控制到每一个按钮,也就是每一个请求。

首先,用户权限校验的基本流程是,当用户登录成功后,将用户对应的权限存放在缓存中,用户每次发起一个请求时,在拦截器里面判断用户是否具有这个权限。

第一步:拦截器的配置

拦截器的配置是在spring-mvc.xml这个配置文件中的。
代码如下:

<!--配置拦截器, 多个拦截器,顺序执行 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller-->
            <mvc:mapping path="/**" />
            <!-- 需排除拦截的地址 -->
            <mvc:exclude-mapping path="/login.ding.jsp"/>
            <mvc:exclude-mapping path="/login.pcding.jsp"/>
            <mvc:exclude-mapping path="/login.index.jsp"/>
            <mvc:exclude-mapping path="/user/toIndex"/>
            <mvc:exclude-mapping path="/user/toLogin"/>
            <mvc:exclude-mapping path="/www/login.jsp"/>
            <bean class="com.siweisoft.interceptor.UserInfoLoginInterceptor"></bean>
        </mvc:interceptor>
        <!--<mvc:interceptor>-->
            <!--&lt;!&ndash; 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller&ndash;&gt;-->
            <!--<mvc:mapping path="/**" />-->
            <!--<bean class="com.siweisoft.interceptor.LogInterceptor"></bean>-->
        <!--</mvc:interceptor>-->
        <!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 -->
        <mvc:interceptor>
            <!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller-->
            <mvc:mapping path="/**" />
            <!-- 需排除拦截的地址 -->
            <mvc:exclude-mapping path="/login.ding.jsp"/>
            <mvc:exclude-mapping path="/login.pcding.jsp"/>
            <mvc:exclude-mapping path="/login.index.jsp"/>
            <mvc:exclude-mapping path="/user/toIndex"/>
            <mvc:exclude-mapping path="/user/toLogin"/>
            <mvc:exclude-mapping path="/www/login.jsp"/>
            <bean class="com.siweisoft.interceptor.Interceptor1"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

第二步:写一个缓存用于存放用户权限

Java中常用的缓存有memcache ,redis, ehcache ,这里使用一个本地的缓存类来实现一个简单的缓存。
代码如下:

/**
 * 缓存管理类,待优化
 * Created by Robin on 2017-01-16.
 */
public class CacheManager {
    private static HashMap cacheMap = new HashMap();
    private static CacheManager cacheManager=null;

    //单实例构造方法
    private CacheManager(){
        super();
    }

//    /**
//     * 获取缓存实例(单例)
//     * @return
//     */
//    public static CacheManager getCacheManager() {
//        if (cacheManager == null) {
//            cacheManager = new CacheManager();
//        }
//        return cacheManager;
//    }

    /**
     * 清除制定的缓存
      * @param key 待清除缓存项的key
     */
    public synchronized static void clearOnly(String key) {
        cacheMap.remove(key);
    }

    //获取缓存信息
    public static Object getCache(String key) {
        if(key == null || "".equals(key)) {
            throw new NullPointerException("待获取缓存对象的key为null");
        }
        return cacheMap.get(key);
    }

    //设置缓存
    public static synchronized  boolean setCache(String key,Object object) {
        if(key == null || "".equals(key)) {
            throw new NullPointerException("待获取缓存对象的key为null");
        }
        if(hasCache(key)) {
            throw new CacheManagerException("同名缓存已经存在!");
        }
        cacheMap.put(key,object);
        return true;
    }

    //判断缓存key是否已经存在
    public static boolean hasCache(String key) {
        return cacheMap.containsKey(key);
    }

    //获取缓存的数目
    public static int getCacheSize() {
        return cacheMap.size();
    }

    //获取缓存对象中的所有键值名称
    public static ArrayList getCacheAllkey() {
        ArrayList a = new ArrayList();
        try {
            Iterator i = cacheMap.entrySet().iterator();
            while (i.hasNext()) {
                java.util.Map.Entry entry = (java.util.Map.Entry) i.next();
                a.add((String) entry.getKey());
            }
        } catch (Exception ex) {} finally {
            return a;
        }
    }

    //清除所有缓存
    public synchronized static void clearAll() {
        cacheMap.clear();
    }

    public static void main(String[] args) {
        CacheManager.setCache("1",1);
        System.out.println("cache:"+ CacheManager.getCache("1"));

        CacheManager.setCache("2",2);

        System.out.println(CacheManager.getCache(""));
    }
}

第三步:编写拦截器,对每一个请求进行校验
代码如下:

/**
 * Created by Robin on 2017-3-10.
 */
public class RequestInterceptor implements HandlerInterceptor {

    //boolean:表示是否需要将当前的请求拦截下来
    //Object handler : 表示当前被拦截的请求的目标对象
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取当前的对象
        User user = (User) request.getSession().getAttribute("user");
        //当前请求的相对url
        String requestUrl = request.getRequestURI();
        //当前缓存中的URL
        List<Map<String,Object>> list = (List<Map<String, Object>>) CacheManager.getCache("UserPer");
        boolean statu = false;
        if (list != null) {
            for (int i = 0; i < list.size(); i++) {
                String url = (String) list.get(i).get("permission_url");
                statu |= requestUrl.equals(url);
          }
        }else{
            statu = false;
        }

//      判断是异步请求还是同步请求,如果是ajax请求响应头会有x-requested-with
        String xrw  = request.getHeader("X-Requested-With");
        if (!statu && xrw!=null){
           response.setStatus(403);
        }
//       同步请求
        if (!statu && xrw == null) {
            response.setHeader("Content-type", "text/html;charset=UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.getWriter().print("<script >alert('您没有此访问权限!');history.go(-1);</script>");
        }
        return statu;
    }

    //返回modelAndView之前执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    //执行Handler完成执行此方法
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }
}

第四步:用户登录成功时,将用户权限存储在缓存类中
代码如下:

//   登录成功后跳转到首页
    @RequestMapping(value="toIndex",method= RequestMethod.GET)
    public String toIndex(int id,HttpServletRequest request) {
        String url = "";
        try {
            User user = userService.selectByPrimaryKey(id);
            if(user!=null&&!user.equals("")){
                request.getSession().setAttribute("user",user);
                //这里将用户的登录信息存储在缓存中
                LoginUserCache.put(user,30*60);
                //通过userID查当前用户的所有权限
                List<Map<String,Object>> list = permissionService.findPermissionByUserId(id);
                CacheManager.clearAll();
                // 这里将用户的权限信息存储在缓存中
                CacheManager.setCache("UserPer",list);
                url = "../../swindex";
            }else{
                url = "../../index";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return url;
    }

这样,一个比较完善的用户权限控制就完成了,如有错误之处,还望及时指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值