权限系统设计

一、概念

权限管理就是管理用户对于资源的操作,CRM(客户管理软件)基于角色操作权限来实现的,就是用户通过角色和权限来实现的。

二、数据库

一共涉及5张表

三张主表

user表(用户表)

role表(角色表)

module表(模块表,资源表)

两张中间表

user_role表(user,role中间表)

role_module表(role,module中间表)

复制代码
 1 --创建用户表
 2 create table users(
 3 --主键
 4 id number(10) primary key,
 5 --用户名
 6 username varchar2(100),
 7 --密码
 8 password varchar2(100),
 9 --地址
10 address varchar2(100)
11 );
12 --创建角色表
13 create table role(
14 --主键
15 id number(10) primary key,
16 --角色名称
17 name varchar2(100)
18 );
19 --创建模块表
20 create table module(
21 --主键
22 id number(10) primary key,
23 --模块名称
24 name varchar2(100),
25 --模块级别
26 level_ number(3),
27 --父模块id
28 pid number(10),
29 --模块路径
30 url varchar2(100)
31 );
32 --创建用户角色中间表
33 create table user_role(
34 --用户表外键
35 u_id number(10),
36 --角色表外键
37 r_id number(10)
38 );
39 --创建角色模块中间表
40 create table role_module(
41 --角色表外键
42 r_id number(10),
43 --模块表外键
44 m_id number(10)
45 );
46 --往用户表插入数据
47 insert into users values(1,'zhangsan','123456','郑州');
48 insert into users values(2,'lisi','123456','郑州');
49 --往角色表插入数据
50 insert into role values(1,'普通用户');
51 insert into role values(2,'管理员');
52 --往模块表插入数据
53 insert into module values(1,'系统管理',1,null,null);
54 insert into module values(2,'订单管理',1,null,null);
55 insert into module values(3,'用户管理',2,1,'user/list.do');
56 insert into module values(4,'角色管理',2,1,'role/list.do');
57 insert into module values(5,'模块管理',2,1,'mod/list.do');
58 insert into module values(6,'出库单管理',2,2,'ckd/list.do');
59 insert into module values(7,'入库单管理',2,2,'rkd/list.do');
60 --为张三用户赋予管理员的角色,为李四赋予普通用户的角色
61 insert into user_role values(1,2);
62 insert into user_role values(2,1);
63 --让管理员可以看到所有的菜单 普通用户只能看到订单管理下所有的菜单
64 insert into role_module values(2,1);
65 insert into role_module values(2,2);
66 insert into role_module values(2,3);
67 insert into role_module values(2,4);
68 insert into role_module values(2,5);
69 insert into role_module values(2,6);
70 insert into role_module values(2,7);
71 insert into role_module values(1,2);
72 insert into role_module values(1,6);
73 insert into role_module values(1,7);
74 select * from users;
75 select * from role;
76 select * from user_role;
77 select * from module;
78 select * from role_module;
复制代码

三、权限管理的步骤

第一步,用户登陆成功之后,根据用户的id查询出用户所能操作的模块,模块一般包含两级。

sql语句的作用:根据用户id查询用户能操作的模块

 查询出来之后,把用户能操作的模块封装到List中:

第二步,在登陆之后跳转到主界面,用jstl标签库把用户能操作的模块动态的遍历出来

 第三步,登陆校验

1、用户登陆成功之后,把当前用户对象放置到session中

 

2、声明用户登陆的拦截器

复制代码
 1 package com.aaa.ssm.interceptor;
 2 import com.aaa.ssm.common.Constants;
 3 import com.aaa.ssm.entity.Users;
 4 import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;import javax.servlet.http.HttpServletRequest;
 5 import javax.servlet.http.HttpServletResponse;
 6 import javax.servlet.http.HttpSessionimport java.util.List;
 7 /**
 8 * 用户登录校验拦截器
 9 */
10 public class LoginInterceptor extends HandlerInterceptorAdapter {
11 private List<String> allowUrls;
12 @Override
13 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
14 throws Exception {
15 //获取当前请求的路径
16 String path = request.getServletPath();
17 //判断当前请求的路径是否在运行直接访问的路径中,如果在直接返回true
18 if(allowUrls.contains(path)){
19 return true;
20 }
21 //获取Session
22 HttpSession session = request.getSession();
23 //获取Session中的用户对象
24 Users user = (Users)session.getAttribute(Constants.SESSION_USER);
25 //判断user对象是否为空,如果为空跳转到登录界面
26 if(user==null){
27 //跳转到登录界面
28 response.sendRedirect(request.getContextPath()+"/login.jsp");
29 return false;
30 }else{
31 return true;
32 }
33 }
34 public List<String> getAllowUrls() {
35 return allowUrls;
36 }
37 public void setAllowUrls(List<String> allowUrls) {
38 this.allowUrls = allowUrls;
39 }
40 }
复制代码

3、在spring mvc主配置文件中声明拦截器

第四步、权限校验

1、用户登陆成功之后把用户能操作的所有的路径信息放置到list中,并把该信息存储到session中

复制代码
 1 /**
 2 * 查询用户能操作的所有二级模块的命名空间
 3 * @param moules
 4 * @return
 5 */
 6 public List<String> queryPermitUrls (List<Module> moules){
 7 List<String> strs = new ArrayList<String>();
 8 for(Module oneModule : moules){
 9 List<Module> twoModules = oneModule.getChildren();
10 for(Module twoModule : twoModules){
11 String url = twoModule.getUrl();
12 strs.add(url.substring(0,url.indexOf("/")));
13 }
14 }
15 return strs;
16 }
复制代码

2、声明用户权限校验的拦截器

复制代码
 1 package com.aaa.ssm.interceptor;
 2 import com.aaa.ssm.common.Constants;
 3 import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
 4 import javax.servlet.http.HttpServletRequest;
 5 import javax.servlet.http.HttpServletResponse;
 6 import javax.servlet.http.HttpSessionimport java.util.List;
 7 /**
 8 * 用户权限校验拦截器
 9 */
10 public class PermitInterceptor extends HandlerInterceptorAdapter {
11 private List<String> allowUrls;
12 @Override
13 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
14 throws Exception {
15 //先获取请求的路径
16 String path = request.getServletPath();
17 //判断当前请求的路径是否在运行直接访问的路径中,如果在直接返回true
18 if(allowUrls.contains(path)){
19 return true;
20 }
21 //判断用户当前的请求,在不在权限范围之内
22 //可以根据用户id查询出来所有用户能操作的模块的路径,把这些路径放置到List集合中,
23 //让后再判断该list集合中有没有当前请求的路径,如果有的话 返回true继续访问,否则跳转到权限不足界面
24 //上面做法的第一个问题:如果在拦截器中每次都查询数据库,前台基本上所有请求都会经过该拦截器,势必响原先
25 //请求的访问效率。我们可以在用户登录成功之后把用户能操作的模块的信息放置到session中,这样在拦截每次都从
26 //session中获取数据,速度就快多了。
27 HttpSession session = request.getSession();
28 //获取用户能操作的模块的命名空间
29 List<String> permitNamespaces = (List<String>)session.getAttribute(Constants.PERMIT_URLS);
30 //判断path是否在permitNamespaces中,如果在证明有权限 返回true 否则返回false 跳转到权限不足的界//获取当前请求的路径命名空间
31 String namespace = path.substring(1,path.lastIndexOf("/"));
32 if(permitNamespaces.contains(namespace)){
33 return true;
34 }else{
35 response.sendRedirect(request.getContextPath()+"/error.jsp");
36 return false;
37 }
38 }
39 public List<String> getAllowUrls() {
40 return allowUrls;
41 }
42 public void setAllowUrls(List<String> allowUrls) {
43 this.allowUrls = allowUrls;
44 }
45 }
复制代码

3、把拦截器加入到spring mvc 主配置文件中

总结:

动态菜单:

第一个要点:表结构和数据 用户表 角色表 模块表 用户角色中间表 角色模块中间表
第二个要点:用户登录成功之后,先根据的用户id获取用户能操作的一级模块,再循环遍历一级模块,把用户 能操作的二级模块封装到一级模块的children属性中。
第三个要点:jsp界面使用两个c:foreach把用户能操作的菜单动态的输出出来。

登录校验

第一个要点:用户登录成功之后,把当前的用户对象放置到Session中
第二个要点:声明登录校验的拦截器,需要不拦截一些特定的请求,如登录请求。拦截器中获取session,获 取session中的用户对象,如果用户对象不存在,跳转到登录界面。存在,继续访问。
第三个要点:配置拦截器。

权限校验 为了防止没有权限的用户通过其他手段直接请求控制器方法。

第一个要点:用户登录成功之后,把用户能操作的命名空间保存到session中。List.
第二个要点:声明权限校验拦截器。需要不拦截一些特定的请求,如登录请求。获取sesson,获取session的 用户能操作的命名空间,获取用户的当前的请求路径,根据请求路径可以把命名空间截取出来。然后判断用 户当前请求的命名空间在不在session中保存用户可操作的命名空间中。如果在直接访问。不在跳转到权限不 足的界面。  
原文地址:https://www.cnblogs.com/duguangming/p/11047405.html