02 OA系统 (权限模块)

【权限】


 系统中提供了很多功能, 但是并不是所有用户都能操作这些功能。
 我们需要对这些功能访问进行控制

 1. 认证
 系统提供的用于识别用户身份的功能, 通常登陆就是认证
 (让系统知道你是谁)

 2. 授权
 系统授予用户可以操作某些功能的许可
 (让系统知道你能做什么)

【常见的权限控制方式】

 1. URL拦截权限控制
 使用过滤器或者拦截器拦截客户端发送的请求,
 在过滤器或者拦截器中进行权限的效验
 如果效验通过, 放行。
 效验不通过, 跳转到权限不足的页面。

 2. 方法注解权限控制
 底层基于代理技术实现

 如
 @HasPrivilege("staff.delete")    // 执行这个方法需要delete权限 
 public String delete(){
    // 调用service删除
 }


【权限模块数据模型】


用户表(多对多)角色表(多对多)权限表


菜单表(多对多)权限表(多对多)操作表


【任务】

 1. 登陆后显示对应的菜单

首先要知道菜单的样式是父子菜单

所以返回的菜单对象不能单纯的List<Menu>,而是List<MenuVo>  

public class MenuVo {
    private Integer menuid;

    private String menuname;

    private String menuurl;

    private Menu pid;
    //子菜单
    private List<Menu> childList;

 登陆成功后,根据用户id查询该用户的所有角色id(用户角色表)

  在控制层的登录方法中

//权限认证,返回的是菜单信息
List<MenuVo> list = us.getMenuVo(user); 

service层中的方法:

   根据所有角色id查询所有权限id(角色权限表)
    根据所有权限id查询所有菜单id(权限菜单表)
    根据所有菜单id查询菜单信息(菜单表)
    菜单信息PO -> VO(内部包含自己的List)

	@Override
	public List<MenuVo> getMenuVo(User user) {
		System.out.println("user"+user);
//		登陆成功后,根据用户id查询该用户的所有角色id(用户角色表)
		List<Integer> permissionidList = getPerListByUserid(user.getUserid());
//		根据所有权限id查询所有菜单id(权限菜单表)
		PermissionMenuExample permissionMenuExample = new PermissionMenuExample();
		cn.zzpigt.bean.PermissionMenuExample.Criteria permissMenuCriteria = permissionMenuExample.createCriteria();
		permissMenuCriteria.andPermissionidIn(permissionidList);
		List<PermissionMenu> permenuList = permissionMenuMapper.selectByExample(permissionMenuExample);
		List<Integer> menuidList = new ArrayList<>();
		if(permenuList == null || permenuList.size() == 0){
			return null;
		}
		for (PermissionMenu pm : permenuList) {
			menuidList.add(pm.getMenuid());
		}
		System.out.println("所有菜单id"+menuidList);
//		根据所有菜单id查询菜单信息(菜单表)
//		菜单信息PO -> VO(内部包含自己的List)
		List<MenuVo> list = new ArrayList<>();
		for (Integer menuid : menuidList) {
			//根据id查到这个menu
			Menu menu = menuMapper.selectByPrimaryKey(menuid);
			MenuVo menuVo = new MenuVo(menu);
			//vo中的pid父菜单
			menuVo.setPid(menuMapper.selectByPrimaryKey(menu.getPid()));
			//list中的子菜单
			MenuExample menuExample = new MenuExample();
			cn.zzpigt.bean.MenuExample.Criteria menuCriteria = menuExample.createCriteria();
			menuCriteria.andPidEqualTo(menuid);
			List<Menu> childList = menuMapper.selectByExample(menuExample);
			menuVo.setChildList(childList);
			list.add(menuVo);
		}
		for (MenuVo menuVo : list) {
			System.out.println("这是menuvo测试循环: "+menuVo);
		}
		return list;
	}


    首页的树形菜单左侧菜单栏用el表达式填充
    子菜单填充到上方

左侧菜单的jsp页面

<!-- 模版的特殊性,左侧菜单栏的data-id需要不同的数,否则会影响到点击选中 -->
<c:set var="listcount" value="2"></c:set>
<!-- 嵌套循环遍历,显示父菜单和子菜单信息 -->
<c:forEach items="${list}" var="menu" varStatus="i">
	<c:if test="${empty (menu.pid) }">
		<li class="nav-li"><a href="javascript:;" class="ue-clear"><i class="nav-ivon"></i><span class="nav-text">${menu.menuname}</span></a>
			<ul class="subnav last-nav-li">
				<c:forEach items="${menu.childList}" var="childMenu" varStatus="j">
					<li href="${pageContext.request.contextPath}/${childMenu.menuurl}/list.action"class="subnav-li "data-id="${listcount }">
                        <a href="${pageContext.request.contextPath }/${childMenu.menuurl}/list.action" class="ue-clear">
                            <i class="subnav-icon"></i><span class="subnav-text">${childMenu.menuname }</span>
                        </a>
                    </li>
                    <!-- 模版的特殊性,左侧菜单栏的data-id需要不同的数,否则会影响到点击选中 -->
					<c:set var="listcount" value="${listcount+1}" />
				</c:forEach>
			</ul>
        </li>
	</c:if>
</c:forEach>

 2. 拦截用户不具备权限的请求

在用户登录成功后返回的用户对象,获取用户id

//去业务逻辑层判断数据是否正确 ,要获取session里面的验证码
User user = us.checkUserAndCode(vo, session);
//授权,返回List<String>
List<String> perActionList = us.getPermissionOp(user);
//放入session中给拦截器用
session.setAttribute("perActionList", perActionList);

    根据用户id查询该用户的所有角色id(用户角色表)
    根据角色id查询所有权限id(角色权限表)
    根据所有权限id查询所有操作id(权限操作表)
    根据所有操作id查询操作信息(操作表)

	@Override
	public List<String> getPermissionOp(User user) {
//		从session取出用户id,用户id查询该用户的所有角色id(用户角色表)
//		根据所有角色id查询所有权限id(角色权限表)
		List<Integer> permissionidList = getPerListByUserid(user.getUserid());
//		根据所有权限id查询所有操作id(权限操作表)
		PermissionOperateExample permissionOperateExample = new PermissionOperateExample();
		cn.zzpigt.bean.PermissionOperateExample.Criteria perOperateCriteria = permissionOperateExample.createCriteria();
		perOperateCriteria.andPermissionidIn(permissionidList);
		
		List<PermissionOperate> perOperateList = perOperateMapper.selectByExample(permissionOperateExample);
		List<Integer> operateidList = new ArrayList<>();
		if(perOperateList == null || perOperateList.size() == 0){
			return null;
		}
		for (PermissionOperate permissionOperate : perOperateList) {
			operateidList.add(permissionOperate.getOperateid());
		}
//		根据所有操作id查询操作信息(操作表)
		OperateExample operateExample = new OperateExample();
		cn.zzpigt.bean.OperateExample.Criteria operaterCriteria = operateExample.createCriteria();
		operaterCriteria.andOperateidIn(operateidList);
		
		List<Operate> operateList = operateMapper.selectByExample(operateExample);
		List<String> operateActionList = new ArrayList<>();
		for (Operate operate : operateList) {
			operateActionList.add(operate.getOperateaction());
		}
		System.out.println("operateActionList"+operateActionList);
		return operateActionList;
	}


    放到session中

    用户发出请求时, 由权限拦截器拦截
    (可设置在登陆拦截器之后)

springmvc配置文件中添加拦截器

	<!-- 配置拦截器 -->
	<mvc:interceptors>
		
		<mvc:interceptor>
			<mvc:mapping path="/**" />
			<!-- 授权拦截器 -->
			<bean class="cn.zzpigt.interceptor.PermissionInterceptor" />
		</mvc:interceptor>
	</mvc:interceptors>

    从session操作信息
    遍历操作信息(或使用contains),判断用户是否有权限进行本次访问。
    这个拦截器还是要再做一次登陆拦截器的逻辑,因为是全局的拦截器,所以用户登录或者获取验证码的时候也要走这个拦截器,蛋疼.

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception {

		User user = (User) request.getSession().getAttribute("user");
		//权限拦截
		List<String> operate =  (List<String>) request.getSession().getAttribute("perActionList");
		if(operate != null && operate.size() > 0){
			//遍历用户权限列表,和看看是否包含请求的url
			for (String op : operate) {
				if(request.getRequestURI().contains(op) || request.getRequestURI().contains("depttable")|| request.getRequestURI().contains("Attend")|| request.getRequestURI().contains("User")){
					System.out.println("没被拦截的,通过:" + request.getRequestURI());
					return true;
				}
			}
		}
		//登录或者获取验证码的情况放行
		else if(user != null || request.getRequestURI().contains("login") || request.getRequestURI().contains("checkCode")){
			return true;
		}
		System.out.println("被拦截的:" + request.getRequestURI());
        //被拦截就重定向到首页
		response.sendRedirect(request.getContextPath() + "/main.jsp");
		return false;
		
	}


[SQL测试]

    登陆成功后,根据用户id查询该用户的所有角色id(用户角色表)

    21
    SELECT roleid FROM user_role WHERE userid = 21;

27


    根据所有角色id查询所有权限id(角色权限表)

    SELECT permissionid FROM role_permission WHERE roleid IN (27);

2
3
4
5
13
14
15
16
18


    根据所有权限id查询所有菜单id(权限菜单表)

SELECT menuid FROM permission_menu WHERE permissionid IN (2,3,4,5,13,14,15,16,18);

2
3
4
5
13
14
15
16
18

    根据所有菜单id查询菜单信息(菜单表)

SELECT * FROM menu WHERE menuid IN (2,3,4,5,13,14,15,16,18);

猜你喜欢

转载自blog.csdn.net/qq_36194262/article/details/85302989
今日推荐