通俗易懂權(quán)限管理模塊設(shè)計-Java

最近一直在做CMS系統(tǒng),發(fā)現(xiàn)一些內(nèi)容其實都是重復(fù)出現(xiàn)的,例如權(quán)限管理模塊。權(quán)限管理模塊就是為了管理用戶是否有權(quán)利訪問某個權(quán)限,如果不能則拒絕訪問。其實Java中已經(jīng)有很成熟的權(quán)限管理框架,例如 Shiro,Spring Security等,也推薦大家使用。但是一些設(shè)計上的東西還是要重復(fù)再造過輪子才能發(fā)現(xiàn)里面的精髓,所以這份代碼,供不太明白的同學(xué)也參考參考。

代碼分享在 Github 上,歡迎大家指出問題: https://github.com/yixiaoming/cms

下面我將詳細介紹一下這個簡單的權(quán)限管理模塊,以便大家可以拿去直接使用。

數(shù)據(jù)表

b384b36c-ccec-46bd-9cdb-c7590f918b2f.png

主要三張表

  • t_user:用戶表,訪問系統(tǒng)的對象
  • t_permission:權(quán)限表,每條記錄就是一個權(quán)限,也就是一個 url 地址
  • t_group:用戶組表,一個組可以包含多個權(quán)限,用戶如果在這個組中,則享有所有權(quán)限

簡單例子

來個簡單的例子,例如一個CMS系統(tǒng)中,有一些權(quán)限:添加文章( /admin/article/add),查看文章( /admin/article/{id}),刪除文章( /admin/delete/{id}),修改文章( /admin/article/update/{id}),每個權(quán)限其實對應(yīng)一個controller的 requet 地址。這些內(nèi)容存放在 t_permission 中。

然后系統(tǒng)中有一些用戶都放在 t_user中,然后我可以為 每個user 分配一些權(quán)限,一個user叫 張三,我可以給他直接添加權(quán)限:查看文章。那么他只能查看,不能增刪改。

然后用戶組表可以看作一個部門,例如一個用戶組叫:文章管理組,那么這個組可以添加:文章的增刪改查4項權(quán)限。現(xiàn)在我再將 user分配到 文章管理組 中,那么張三就擁有了 文章的增刪改查的所有權(quán)限。

最主要的思想就是:用戶的權(quán)限,可以直接分配,也可以通過用戶組來分配,用戶的所有權(quán)限就是兩者的并集

框架

  1. Spring 4.26
  2. Hibernate 5.10
  3. Java 8

例子采用 SpringMVC + Hibernate + Bootstrap搭建,簡單實用,對于小項目使用絕對沒有問題。
然后里面也用到了一些開源的Web前端項目,例如SB-Admin,Bootstrap Multiselect,MetisMenu,Bootstrap Validation等,由于我本來不是做前端的,所以UI上的東西只能借助開源項目來完成。下面展示一下效果:

登陸頁

2059ba9e-e698-4b5a-8de3-493ab9459bd4.png

用戶列表頁,用戶組列表頁,權(quán)限列表頁 都類似

c0dc39cc-1292-4c8c-bb62-c871a33747e1.png

用戶添加,修改頁:

7a3929cd-e7b6-4696-b8f2-9c99d74412c8.png

選擇權(quán)限

44d54e8a-2ad0-4586-a4fc-70c7fb96f732.png

選擇用戶組

3628bba0-966f-45bd-9e5a-0c3b94a6457f.png

當(dāng)選定了權(quán)限和用戶組,那么用戶的權(quán)限就是 權(quán)限+角色組所有的權(quán)限 的并集。

登陸成功后將所有權(quán)限放在session中:

LoginController

List<Permission> permissions = userService.listUserPermissions(user.getId());
    List<Integer> gids = userService.listUserGids(user.getId());
    List<Permission> groupPermissions = groupService.listGroupsPermissions(ListUtil.list2array(gids));

    for (Permission p : groupPermissions) {
      if (!permissions.contains(p)) {
        permissions.add(p);
      }
    }

    request.getSession().setAttribute(Constant.LOGIN_USER, user);
    request.getSession().setAttribute(Constant.LOGIN_PERMISSIONS, permissions);

然后寫兩個個攔截器,一個判斷登錄,一個判斷權(quán)限,每次訪問鏈接前先判斷是否有這個權(quán)限,如果沒有則拋出異常。這里有一點還需要注意,如果用戶的類型使 Admin 的話,那么默認就擁有所有權(quán)限,所以不需要驗證。通過 user 的 isAdmin 字段判斷

LoginInterceptor

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
    User user = (User) request.getSession().getAttribute(Constant.LOGIN_USER);
    if (request.getRequestURL().toString().contains("/admin")) {
      if (user == null) {
        response.sendRedirect(request.getContextPath() + "/login");
        return false;
      }
    }
    return true;
  }

PermissionInterceptor

 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
    String url = request.getRequestURL().toString();
    if (url.contains("/admin")) {
      List<Permission> permissions = (List<Permission>) request.getSession().getAttribute(Constant.LOGIN_PERMISSIONS);
      User user = (User) request.getSession().getAttribute(Constant.LOGIN_USER);

      if (permissions == null || user == null) {
        response.sendRedirect(request.getContextPath() + "/login");
        return false;
      }

      // 如果是admin,就不需要權(quán)限驗證
      if (user.getAdmin()) {
        return true;
      }

      boolean hasPermission = false;
      for (Permission permission : permissions) {
        if (url.contains(permission.getUrl())) {
          hasPermission = true;
          break;
        }
      }

      if (!hasPermission) {
        throw new CmsException("沒有權(quán)限訪問:" + url);
      }
    }

    return true;
  }

總結(jié)

這里洋洋灑灑的寫了一些權(quán)限模塊中的內(nèi)容,只是里面的主線,細節(jié)的代碼大家可以參考Github上的代碼地址鏈接,大神略過。希望能給正在學(xué)習(xí)這個內(nèi)容的同學(xué)一點幫助,反正造這個輪子,我學(xué)到了不少。。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,982評論 19 139
  • Ubuntu的發(fā)音 Ubuntu,源于非洲祖魯人和科薩人的語言,發(fā)作 oo-boon-too 的音。了解發(fā)音是有意...
    螢火蟲de夢閱讀 99,587評論 9 467
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,476評論 25 708
  • CREATE TABLE IF NOT EXISTS ecs_order_info (order_id mediu...
    cookie口閱讀 15,768評論 0 16
  • 建筑外墻裝飾材料環(huán)保要求 在建筑裝飾材料中涉及環(huán)保的環(huán)節(jié)主要有:原材料獲取可持續(xù)發(fā)展、不能對自然資源帶來掠奪性傷害...
    黃俊凌閱讀 575評論 0 2