一、概念
权限管理就是管理用户对于资源的操作,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中保存用户可操作的命名空间中。如果在直接访问。不在跳转到权限不 足的界面。