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

来源:互联网 发布:淘宝充流量为什么便宜 编辑:程序博客网 时间:2024/04/29 04:19

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

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

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


接下来编码实现:
我们要修改我们过滤器的代码
[java] view plaincopy
  1. @Override  
  2. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,  
  3.         FilterChain chain) throws IOException, ServletException {  
  4.     HttpServletRequest request=(HttpServletRequest)servletRequest;  
  5.     HttpServletResponse response=(HttpServletResponse)servletResponse;  
  6.     String uri=request.getRequestURI();  
  7.     //判断当前请求地址是否是登录地址  
  8.     if(!uri.contains("sys/login_")){  
  9.         //非登录请求  
  10.         if(request.getSession().getAttribute(Constant.USER)!=null){  
  11.             //说明已经登录过  
  12.             //判断是否访问纳税服务子系统  
  13.             if(uri.contains("/tax/")){  
  14.                 //说明访问纳税服务子系统  
  15.                 User user=(User)request.getSession().getAttribute(Constant.USER);  
  16.                 PermissionCheck pc=new PermissionCheckImpl();  
  17.                 if(pc.isAccessible(user,"nsfw")){  
  18.                     //说明有权限,放行  
  19.                     chain.doFilter(request, response);  
  20.                 }else{  
  21.                     //没有权限,跳转到没有权限提示界面  
  22.                     response.sendRedirect(request.getContextPath()+"/sys/login_toNoPermissionUI.action");  
  23.                 }  
  24.                       
  25.             }else{  
  26.                 //非访问纳税服务子系统,直接放行  
  27.                 chain.doFilter(request, response);  
  28.             }  
  29.               
  30.         }else{  
  31.             //没有登录,跳转到登录界面  
  32.             response.sendRedirect(request.getContextPath()+"/sys/login_toLoginUI.action");  
  33.         }  
  34.     }else{  
  35.         //登录请求,直接放行  
  36.         chain.doFilter(request, response);  
  37.     }  
  38. }  

其中新添加了权限检查类PermissionCheck(分为接口和实现类),此类代码为:
接口:
[java] view plaincopy
  1. package cn.edu.hpu.tax.core.permission;  
  2.   
  3. import cn.edu.hpu.tax.user.entity.User;  
  4.   
  5. public interface PermissionCheck {  
  6.     /** 
  7.      *判断用户是否有code对应的权限 
  8.      * @param user 用户 
  9.      * @param code 子系统的权限标识 
  10.      * @return true or false 
  11.      */  
  12.     public boolean isAccessible(User user,String code);  
  13. }  

实现类:
[java] view plaincopy
  1. package cn.edu.hpu.tax.core.permission.impl;  
  2.   
  3. import javax.annotation.Resource;  
  4.   
  5. import cn.edu.hpu.tax.core.permission.PermissionCheck;  
  6. import cn.edu.hpu.tax.role.entity.Role;  
  7. import cn.edu.hpu.tax.role.entity.RolePrivilege;  
  8. import cn.edu.hpu.tax.role.service.RoleService;  
  9. import cn.edu.hpu.tax.user.entity.User;  
  10. import cn.edu.hpu.tax.user.service.UserService;  
  11.   
  12. public class PermissionCheckImpl implements PermissionCheck {  
  13.   
  14.   
  15.     @Resource  
  16.     private UserService userService;  
  17.     @Resource  
  18.     private RoleService roleService;  
  19.       
  20.     @Override  
  21.     public boolean isAccessible(User user, String code) {  
  22.         //1.获取用户的所有角色  
  23.         String[] ids=userService.getRoleIdByUserId(user.getId());  
  24.         Role role=null;  
  25.         //2.根据每个角色对应的所有权限进行对比  
  26.         for (int i = 0; i < ids.length; i++) {  
  27.             role=roleService.findObjectById(ids[i]);  
  28.             for (RolePrivilege rp:role.getRolePrivileges()) {  
  29.                 //对比是否有code对应的权限  
  30.                 if(code.equals(rp.getId().getCode())){  
  31.                     //说明有权限,返回true  
  32.                     return true;  
  33.                 }  
  34.             }  
  35.         }  
  36.         return false;  
  37.     }  
  38.   
  39.   
  40. }  

在LoginAction中添加跳转到没有权限提示界面的方法:
[java] view plaincopy
  1. //跳转到没有权限提示界面  
  2. public String toNoPermissionUI(){  
  3.     return "noPermissionUI";  
  4. }  

然后在struts中配置这个界面:
[html] view plaincopy
  1. <result name="noPermissionUI">/WEB-INF/jsp/noPermissionUI.jsp</result>  

没有权限访问模块的noPermissionUI.jsp界面代码:
[html] view plaincopy
  1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
  2. <html>  
  3.   <head>  
  4.     <title>没有权限</title>  
  5.   </head>  
  6.     
  7.   <body>  
  8.         对不起!您没有访问此功能的权限;请联系系统管理员。      
  9.         <a href="javascript:history.go(-1)">《《返回</a>  
  10.   </body>  
  11. </html>  

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

然后在LoginAction的login方法中登录之后就将用户的所有权限信息都保存在用户的roles属性中(需要注入roleService),然后再将用户放入session,以后就可以利用session中的信息,无需再次查询数据库:
[java] view plaincopy
  1. //登录  
  2. public String login(){  
  3.     if(user!=null){  
  4.         if(StringUtils.isNoneBlank(user.getAccount())  
  5.                 &&StringUtils.isNoneBlank(user.getPassword())){  
  6.             //根据用户的账号和密码查询用户列表  
  7.             List<User> list=userService.findUserByAccountAndPassword(user.getAccount(),user.getPassword());  
  8.             if(list!=null&&list.size()>0){//说明登录成功  
  9.                 //1、登录成功  
  10.                 User user=list.get(0);  
  11.                 //1.1、根据用户id查询用户的所有角色信息  
  12.                 String[] ids=userService.getRoleIdByUserId(user.getId());  
  13.                 List<Role> rolelist=new ArrayList<Role>();  
  14.                 for (int i = 0; i < ids.length; i++) {  
  15.                     rolelist.add(roleService.findObjectById(ids[i]));  
  16.                 }  
  17.                 user.setRoles(rolelist);  
  18.                 //1.2、将用户信息保存到session中  
  19.                 ServletActionContext.getRequest().getSession().setAttribute(Constant.USER, user);  
  20.                 //1.3、将用户登录记录到日志文件  
  21.                 Log log=LogFactory.getLog(getClass());  
  22.                 log.info("用户名称为:"+user.getName()+"的用户登录了系统");  
  23.                 //1.4、重定向跳转到首页  
  24.                 return "home";  
  25.             }else{  
  26.                 loginResult="账号或密码不正确!";  
  27.             }  
  28.         }else{  
  29.             loginResult="账号或密码不能为空!";  
  30.         }  
  31.     }else{  
  32.         loginResult="请输入账号和密码!";  
  33.     }  
  34.     return toLoginUI();  
  35. }  


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

[java] view plaincopy
  1. package cn.edu.hpu.tax.core.permission.impl;  
  2.   
  3. import java.util.List;  
  4.   
  5. import cn.edu.hpu.tax.core.permission.PermissionCheck;  
  6. import cn.edu.hpu.tax.role.entity.Role;  
  7. import cn.edu.hpu.tax.role.entity.RolePrivilege;  
  8. import cn.edu.hpu.tax.user.entity.User;  
  9.   
  10. public class PermissionCheckImpl implements PermissionCheck {  
  11.   
  12.     @Override  
  13.     public boolean isAccessible(User user, String code) {  
  14.         //1.获取用户的所有角色  
  15.         List<Role> rolelist=user.getRoles();  
  16.         Role role=null;  
  17.         //2.根据每个角色对应的所有权限进行对比  
  18.         for (int i = 0; i < rolelist.size(); i++) {  
  19.             role=rolelist.get(i);  
  20.             for (RolePrivilege rp:role.getRolePrivileges()) {  
  21.                 //对比是否有code对应的权限  
  22.                 if(code.equals(rp.getId().getCode())){  
  23.                     //说明有权限,返回true  
  24.                     return true;  
  25.                 }  
  26.             }  
  27.         }  
  28.         return false;  
  29.     }  
  30.   
  31.   
  32. }  

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


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

还有一个问题,我们删除用户的时候是物理删除(当然后期不是物理删除),我们删除用户之后还需要将用户所有的角色信息给删除,防止脏数据。
所以我们修改UserServiceImpl的delete方法:
[java] view plaincopy
  1. @Override  
  2. public void delete(Serializable id) {  
  3.     userDao.delete(id);  
  4.     //删除用户对应的所有权限  
  5.     userDao.deleteUserRoleByUserId(id.toString());  
  6. }  

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

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

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

解决办法:
就是让登录界面知道自己在哪里(浏览器里还是frame里)
找到我们的登录jsp,在其中添加此代码:
[javascript] view plaincopy
  1. //解决子框架嵌套的问题  
  2. if(window != window.parent){  
  3.     window.parent.location.reload(true);  
  4. }  

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

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

0 0
原创粉丝点击