【SSH项目实战】国税协同平台-17.权限鉴定&解决登录嵌套

我们上一次完成了登录功能和session用户信息的保存和注销。下面我们完成登陆后有关权限鉴定的功能。

我们系统分了5大子系统,粗粒度的分了5个权限。

用户只要有对应系统的权限才可以访问相应的子系统。超级管理员可以访问所有子模块,一般的用户可能只能访问“我的空间”。

我们下面就来做一个权限鉴定,我们画个图来设计一下:

接下来编码实现:
我们要修改我们过滤器的代码

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
		FilterChain chain) throws IOException, ServletException {
	HttpServletRequest request=(HttpServletRequest)servletRequest;
	HttpServletResponse response=(HttpServletResponse)servletResponse;
	String uri=request.getRequestURI();
	//判断当前请求地址是否是登录地址
	if(!uri.contains("sys/login_")){
		//非登录请求
		if(request.getSession().getAttribute(Constant.USER)!=null){
			//说明已经登录过
			//判断是否访问纳税服务子系统
			if(uri.contains("/tax/")){
				//说明访问纳税服务子系统
				User user=(User)request.getSession().getAttribute(Constant.USER);
				PermissionCheck pc=new PermissionCheckImpl();
				if(pc.isAccessible(user,"nsfw")){
					//说明有权限,放行
					chain.doFilter(request, response);
				}else{
					//没有权限,跳转到没有权限提示界面
					response.sendRedirect(request.getContextPath()+"/sys/login_toNoPermissionUI.action");
				}

			}else{
				//非访问纳税服务子系统,直接放行
				chain.doFilter(request, response);
			}

		}else{
			//没有登录,跳转到登录界面
			response.sendRedirect(request.getContextPath()+"/sys/login_toLoginUI.action");
		}
	}else{
		//登录请求,直接放行
		chain.doFilter(request, response);
	}
}

其中新添加了权限检查类PermissionCheck(分为接口和实现类),此类代码为:
接口:

package cn.edu.hpu.tax.core.permission;

import cn.edu.hpu.tax.user.entity.User;

public interface PermissionCheck {
	/**
	 *判断用户是否有code对应的权限
	 * @param user 用户
	 * @param code 子系统的权限标识
	 * @return true or false
	 */
	public boolean isAccessible(User user,String code);
}

实现类:

package cn.edu.hpu.tax.core.permission.impl;

import javax.annotation.Resource;

import cn.edu.hpu.tax.core.permission.PermissionCheck;
import cn.edu.hpu.tax.role.entity.Role;
import cn.edu.hpu.tax.role.entity.RolePrivilege;
import cn.edu.hpu.tax.role.service.RoleService;
import cn.edu.hpu.tax.user.entity.User;
import cn.edu.hpu.tax.user.service.UserService;

public class PermissionCheckImpl implements PermissionCheck {

	@Resource
	private UserService userService;
	@Resource
	private RoleService roleService;

	@Override
	public boolean isAccessible(User user, String code) {
		//1.获取用户的所有角色
		String[] ids=userService.getRoleIdByUserId(user.getId());
		Role role=null;
		//2.根据每个角色对应的所有权限进行对比
		for (int i = 0; i < ids.length; i++) {
			role=roleService.findObjectById(ids[i]);
			for (RolePrivilege rp:role.getRolePrivileges()) {
				//对比是否有code对应的权限
				if(code.equals(rp.getId().getCode())){
					//说明有权限,返回true
					return true;
				}
			}
		}
		return false;
	}

}

在LoginAction中添加跳转到没有权限提示界面的方法:

//跳转到没有权限提示界面
public String toNoPermissionUI(){
	return "noPermissionUI";
}

然后在struts中配置这个界面:

<result name="noPermissionUI">/WEB-INF/jsp/noPermissionUI.jsp</result>

没有权限访问模块的noPermissionUI.jsp界面代码:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
  <head>
    <title>没有权限</title>
  </head>

  <body>
    	对不起!您没有访问此功能的权限;请联系系统管理员。    
    	<a href="javascript:history.go(-1)">《《返回</a>
  </body>
</html>

我们不能每一次点击一个功能的时候就进行这样一次检查,因为每次都要进行查询数据库来查询用户的角色信息,我们要在登录的时候就去查询完成这个角色,然后之后每次鉴定的时候就无需再次进数据库查询:
我们在User中添加private List<role> roles;这个属性以及get和set方法。

然后在LoginAction的login方法中登录之后就将用户的所有权限信息都保存在用户的roles属性中(需要注入roleService),然后再将用户放入session,以后就可以利用session中的信息,无需再次查询数据库:

//登录
public String login(){
	if(user!=null){
		if(StringUtils.isNoneBlank(user.getAccount())
				&&StringUtils.isNoneBlank(user.getPassword())){
			//根据用户的账号和密码查询用户列表
			List<User> list=userService.findUserByAccountAndPassword(user.getAccount(),user.getPassword());
			if(list!=null&&list.size()>0){//说明登录成功
				//1、登录成功
				User user=list.get(0);
				//1.1、根据用户id查询用户的所有角色信息
				String[] ids=userService.getRoleIdByUserId(user.getId());
				List<Role> rolelist=new ArrayList<Role>();
				for (int i = 0; i < ids.length; i++) {
					rolelist.add(roleService.findObjectById(ids[i]));
				}
				user.setRoles(rolelist);
				//1.2、将用户信息保存到session中
				ServletActionContext.getRequest().getSession().setAttribute(Constant.USER, user);
				//1.3、将用户登录记录到日志文件
				Log log=LogFactory.getLog(getClass());
				log.info("用户名称为:"+user.getName()+"的用户登录了系统");
				//1.4、重定向跳转到首页
				return "home";
			}else{
				loginResult="账号或密码不正确!";
			}
		}else{
			loginResult="账号或密码不能为空!";
		}
	}else{
		loginResult="请输入账号和密码!";
	}
	return toLoginUI();
}

然后修改PermissionCheckImpl的检查代码,让其不再去查询数据库。

package cn.edu.hpu.tax.core.permission.impl;

import java.util.List;

import cn.edu.hpu.tax.core.permission.PermissionCheck;
import cn.edu.hpu.tax.role.entity.Role;
import cn.edu.hpu.tax.role.entity.RolePrivilege;
import cn.edu.hpu.tax.user.entity.User;

public class PermissionCheckImpl implements PermissionCheck {

	@Override
	public boolean isAccessible(User user, String code) {
		//1.获取用户的所有角色
		List<Role> rolelist=user.getRoles();
		Role role=null;
		//2.根据每个角色对应的所有权限进行对比
		for (int i = 0; i < rolelist.size(); i++) {
			role=rolelist.get(i);
			for (RolePrivilege rp:role.getRolePrivileges()) {
				//对比是否有code对应的权限
				if(code.equals(rp.getId().getCode())){
					//说明有权限,返回true
					return true;
				}
			}
		}
		return false;
	}

}

我们来验证一下我们的权限鉴定是否可行:
我们没有给“李向阳”设定访问纳税服务的权限,所以当我们登录李向阳的账号之后点击“纳税服务”模块时,弹出下列窗口:

当我们使用其它有此权限的账号登录的时候,可以进入“纳税服务”模块。
至此,我们的权限鉴定功能完成。

还有一个问题,我们删除用户的时候是物理删除(当然后期不是物理删除),我们删除用户之后还需要将用户所有的角色信息给删除,防止脏数据。
所以我们修改UserServiceImpl的delete方法:

@Override
public void delete(Serializable id) {
	userDao.delete(id);
	//删除用户对应的所有权限
	userDao.deleteUserRoleByUserId(id.toString());
}

这样,当我们删除用户的时候,就会连用户的角色一起删除。

2.登录嵌套的解决
还有一个问题,当我们登陆之后过了好一段时间没有操作,点击某个功能的时候会出现这种情况:

这就是所谓的登录嵌套,是什么原因呢?
原因就是我们的session是有时间限制的,当session失效的时候,点击frame框架里的侧边栏,在右边主界面显示的就是我们的功能模块页面,但是由于我们设置了过滤器,我们的过滤器检测到用户的session不存在,所以就会跳转至登录界面,就造成了上面那种情况。

解决办法:
就是让登录界面知道自己在哪里(浏览器里还是frame里)
找到我们的登录jsp,在其中添加此代码:

//解决子框架嵌套的问题
if(window != window.parent){
	window.parent.location.reload(true);
}

也就是当此界面不是在主窗口的时候,我们就刷新主窗口的地址。

至此,我们的权限鉴定和解决嵌套登录完成。

工程源代码下载:http://download.csdn.net/detail/u013517797/9246763

转载请注明出处:http://blog.csdn.net/acmman/article/details/49680255

时间: 2024-07-28 23:00:31

【SSH项目实战】国税协同平台-17.权限鉴定&amp;解决登录嵌套的相关文章

【SSH项目实战】国税协同平台-1.项目介绍

项目介绍 1.1项目背景 国税协同办公平台包括了行政管理.后勤服务.在线学习.纳税服务.我的空间等几个子系统:我们本次主要的开发功能是纳税服务子系统的部分模块和基于纳税服务子系统信息的个人工作台首页.纳税服务子系统是办税PC前端或移动端的后台管理系统,主要包括的功能有系统角色管理.用户管理.信息发布管理.投诉受理.纳税咨询.易告知.服务预约.服务调查等模块. 系统的主界面: 我们要做的模块界面: 1.2项目前期 项目前期:一般是由客户经理从客户那边了解到有关该项目的招标信息,然后开发公司再组织竞

【SSH项目实战】国税协同平台-14.系统、子系统首页&amp;amp;登录功能1

我们做完了用户与角色的分配,在设置用户在相应的角色下的操作之前,我们先完成用户的登录功能. 首先,我们先加载我们的系统的首页和子首页.很简单,就是转发到一个jsp页面而已,我们先写一个HomeAction来设置跳转功能: package cn.edu.hpu.tax.core.action; import com.opensymphony.xwork2.ActionSupport; public class HomeAction extends ActionSupport{ //跳转到首页 pu

【SSH项目实战】国税协同平台-11.角色权限管理1

我们要完成角色管理这一块,首先我们看一下这一块的需求: I.界面描述 II.功能说明 角色管理:可以根据角色名称查询系统用户:在页面中点击"新增"可以添加用户.点击删除可以批量删除选中的用户.在角色列表中显示角色名称.权限.状态.操作:其中操作列中包括编辑.删除两个功能:点击"编辑"则编辑角色信息,删除则删除该角色. 编辑角色:编辑页面包括角色名称.权限列表(可复选多个权限).状态(有效.无效). 角色与权限的关系: 系统中可以存在多个角色,每个角色可以自由的组合系

【SSH项目实战】国税协同平台-12.角色权限管理2

接上一篇http://blog.csdn.net/acmman/article/details/49512903 然后是action层: package cn.edu.hpu.tax.role.action; import java.util.HashSet; import java.util.List; import javax.annotation.Resource; import cn.edu.hpu.tax.core.action.BaseAction; import cn.edu.hp

【SSH项目实战】国税协同平台-3.资源文件分类&amp;amp;log4j&amp;amp;抽取BaseAction

上次我们搭建了SSH框架的环境,然后做了单元测试,下面我们继续来完善我们工厂的准备工作. 3.1资源文件分类 (1)将配置文件归类到新建config文件夹: (2)源代码目录按照功能模块进行划分:cn.edu.hpu.子系统.功能模块.* (3)Jsp放置到WEB-INF目录下: (4)其它: 新建一个test源文件架(Source Folder),我们把上次所有测试的代码全部移入test文件夹下,然后专门为配置文件创建一个conf源文件夹,将配置文件移入,然后src中先建立一个包准备放新写的代

【SSH项目实战】国税协同平台-31.我要投诉功能1

我们之前完成了投诉回复和保存功能,这次我们将要完成历史受理信息的显示 以及数据回显功能,当然还有用户编写投诉信息的入口,我们这次继续. 可以注意到,在deilUI.jsp上我们之前的投诉人信息显示,不管是匿名还是不匿名,投诉人的姓名.手机号码都是显示出来的: <tr> <td class="tdBg">投诉人姓名:</td> <td><s:property value="complain.compName"/&g

【SSH项目实战】国税协同平台-27.分页对象应用&amp;amp;抽取pageNavigator

上次我们完成了信息发布管理模块的分页功能.但是我们还没给其它的模块做分页,所以我们也要去完成其它模块的分页功能. 按照我们给信息发布管理模块编写分页功能的方式去编写,需要大费周章,我们不如把分页功能封装起来,这样这些模块包括以后扩充的模块都能使用分页的功能了. 我们回顾一下我们的InfoAction,关于分页的属性有: //分页对象 protected PageResult pageResult; //页号 private int pageNo; //页大小 private int pageSi

【SSH项目实战】国税协同平台-21.PowerDesigner概念、物理模型

我们之前做的都是先建实体类再去创建表(或者是hibernate自动生成表),有一个概念叫"逆向工程",就是先创建表,再由表来生成相应的实体类和映射文件. 在讲"逆向工程"之前,我们先学一个数据库模型设计工具,做"PowerDesigner",是设计实体以及实体之间的关系的,而且可以生成数据库建表语句的工具. 我们打开PowerDesigner,创建一个"概念模型",实体集关系表: 然后介绍一下侧面的工具: 上面常用的就这几个

【SSH项目实战】国税协同平台-4.用户管理需求分析&amp;amp;CRUD方法1

上次我们完成了日志模块的配置和基础增删改查类,下面我们根据用户的需求来正式开发项目的业务模块. 下面我们主要来开发系统用户管理的模块 我们有用户的功能说明书,打开功能说明书来看看这个模块需要什么功能: 功能说明 用户管理:可以根据用户名查询系统用户:在页面中点击"新增"可以添加用户.点击删除可以批量删除选中的用户."导出"则导出所有的用户列表到excel文件中并弹出下载提示框给用户下载:"导入"将需要用户将本地的用户列表按照一定格式将excel中