JAVAWEB开发之权限管理(一)——权限管理详解(权限管理原理以及方案)、不使用权限框架的原始授权方式详解
知识清单
权限管理原理知识
什么是权限管理
用户认证
用户认证概念
用户认证流程
关键对象
用户授权
用户授权概念
授权流程
关键对象
权限模型
分配权限
权限控制(授权核心)
基于角色的访问控制
基于资源的访问控制
RBAC (Resource based access control) 基于资源的访问控制
上面的方法就可以解决用户角色变更而不用修改上边权限控制的代码。
权限管理解决方案
什么是粗粒度权限和细粒度权限?
如何实现粗粒度和细粒度的权限管理
基于url拦截的方式实现
使用权限管理框架来实现
基于URL的权限管理
基于url的权限管理流程
搭建环境
数据库
/*
SQLyog v10.2
MySQL - 5.1.72-community : Database - shiro
*********************************************************************
*//*!40101 SET NAMES utf8 */;/*!40101 SET SQL_MODE=''*/;/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
/*Table structure for table `sys_permission` */CREATE TABLE `sys_permission` (`id` bigint(20) NOT NULL COMMENT '主键',`name` varchar(128) NOT NULL COMMENT '资源名称',`type` varchar(32) NOT NULL COMMENT '资源类型:menu,button,',`url` varchar(128) DEFAULT NULL COMMENT '访问url地址',`percode` varchar(128) DEFAULT NULL COMMENT '权限代码字符串',`parentid` bigint(20) DEFAULT NULL COMMENT '父结点id',`parentids` varchar(128) DEFAULT NULL COMMENT '父结点id列表串',`sortstring` varchar(128) DEFAULT NULL COMMENT '排序号',`available` char(1) DEFAULT NULL COMMENT '是否可用,1:可用,0不可用',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;/*Table structure for table `sys_role` */CREATE TABLE `sys_role` (`id` varchar(36) NOT NULL,`name` varchar(128) NOT NULL,`available` char(1) DEFAULT NULL COMMENT '是否可用,1:可用,0不可用',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;/*Table structure for table `sys_role_permission` */CREATE TABLE `sys_role_permission` (`id` varchar(36) NOT NULL,`sys_role_id` varchar(32) NOT NULL COMMENT '角色id',`sys_permission_id` varchar(32) NOT NULL COMMENT '权限id',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;/*Table structure for table `sys_user` */CREATE TABLE `sys_user` (`id` varchar(36) NOT NULL COMMENT '主键',`usercode` varchar(32) NOT NULL COMMENT '账号',`username` varchar(64) NOT NULL COMMENT '姓名',`password` varchar(32) NOT NULL COMMENT '密码',`salt` varchar(64) DEFAULT NULL COMMENT '盐',`locked` char(1) DEFAULT NULL COMMENT '账号是否锁定,1:锁定,0未锁定',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;/*Table structure for table `sys_user_role` */CREATE TABLE `sys_user_role` (`id` varchar(36) NOT NULL,`sys_user_id` varchar(32) NOT NULL,`sys_role_id` varchar(32) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
shiro_sql_table_data.sql
/*
SQLyog v10.2
MySQL - 5.1.72-community : Database - shiro
*********************************************************************
*//*!40101 SET NAMES utf8 */;/*!40101 SET SQL_MODE=''*/;/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
/*Data for the table `sys_permission` */insert into `sys_permission`(`id`,`name`,`type`,`url`,`percode`,`parentid`,`parentids`,`sortstring`,`available`) values
(1,'权限','','',NULL,0,'0/','0','1'),(11,'商品管理','menu','/item/queryItem.action',NULL,1,'0/1/','1.','1'),
(12,'商品新增','permission','/item/add.action','item:create',11,'0/1/11/','','1'),
(13,'商品修改','permission','/item/editItem.action','item:update',11,'0/1/11/','','1'),
(14,'商品删除','permission','','item:delete',11,'0/1/11/','','1'),
(15,'商品查询','permission','/item/queryItem.action','item:query',11,'0/1/15/',NULL,'1'),
(21,'用户管理','menu','/user/query.action','user:query',1,'0/1/','2.','1'),
(22,'用户新增','permission','','user:create',21,'0/1/21/','','1'),
(23,'用户修改','permission','','user:update',21,'0/1/21/','','1'),
(24,'用户删除','permission','','user:delete',21,'0/1/21/','','1');/*Data for the table `sys_role` */insert into `sys_role`(`id`,`name`,`available`) values ('ebc8a441-c6f9-11e4-b137-0adc305c3f28','商品管理员','1'),('ebc9d647-c6f9-11e4-b137-0adc305c3f28','用户管理员','1');/*Data for the table `sys_role_permission` */insert into `sys_role_permission`(`id`,`sys_role_id`,`sys_permission_id`) values ('ebc8a441-c6f9-11e4-b137-0adc305c3f21','ebc8a441-c6f9-11e4-b137-0adc305c','12'),('ebc8a441-c6f9-11e4-b137-0adc305c3f22','ebc8a441-c6f9-11e4-b137-0adc305c','11'),('ebc8a441-c6f9-11e4-b137-0adc305c3f24','ebc9d647-c6f9-11e4-b137-0adc305c','21'),('ebc8a441-c6f9-11e4-b137-0adc305c3f25','ebc8a441-c6f9-11e4-b137-0adc305c','15'),('ebc9d647-c6f9-11e4-b137-0adc305c3f23','ebc9d647-c6f9-11e4-b137-0adc305c','22'),('ebc9d647-c6f9-11e4-b137-0adc305c3f26','ebc8a441-c6f9-11e4-b137-0adc305c','13');/*Data for the table `sys_user` */insert into `sys_user`(`id`,`usercode`,`username`,`password`,`salt`,`locked`) values ('lisi','lisi','李四','bf07fd8bbc73b6f70b8319f2ebb87483','uiwueylm','0'),('zhangsan','zhangsan','张三','cb571f7bd7a6f73ab004a70322b963d5','eteokues','0');/*Data for the table `sys_user_role` */insert into `sys_user_role`(`id`,`sys_user_id`,`sys_role_id`) values ('ebc8a441-c6f9-11e4-b137-0adc305c3f28','zhangsan','ebc8a441-c6f9-11e4-b137-0adc305c'),('ebc9d647-c6f9-11e4-b137-0adc305c3f28','lisi','ebc9d647-c6f9-11e4-b137-0adc305c');/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
查看对应权限模型的数据如下:
sys_permission 权限表
开发环境
系统工程架构
系统登录
用户的身份信息
/*** 用户身份信息,存入Session 由于Tomcat正常关闭时会将Session序列化的本地硬盘上,所以实现Serializable接口* @author liuxun**/
public class ActiveUser implements Serializable {private String userid; //用户id(主键)private String usercode; // 用户账号private String username; // 用户姓名........
}
mapper
mapper接口:根据用户账号查询用户(sys_user)信息 (使用逆向工程生成权限相关的PO类和mapper接口)
service(进行用户名和密码校验)
/*** 认证授权服务接口* @author liuxun**/
public interface SysService {//根据用户的身份和密码进行认证,如果认证通过,返回用户身份信息public ActiveUser authenticat(String usercode,String password) throws Exception;//根据用户账号查询用户信息public SysUser findSysUserByUserCode(String userCode) throws Exception;......
}
方法实现:
public class SysServiceImpl implements SysService {@Autowiredprivate SysUserMapper sysUserMapper;public ActiveUser authenticat(String usercode, String password) throws Exception {/*** 认证过程: 根据用户身份(账号)查询数据库,如果查询不到则用户不存在 * 对输入的密码和数据库密码进行比对,如果一致则认证通过*/// 根据用户账号查询数据库SysUser sysUser = this.findSysUserByUserCode(usercode);if (sysUser == null) {// 抛出异常throw new CustomException("用户账号不存在");}// 数据库密码(MD5加密后的密码)String password_db = sysUser.getPassword();// 对输入的密码和数据库密码进行比对,如果一致,认证通过// 对页面输入的密码进行MD5加密String password_input_md5 = new MD5().getMD5ofStr(password);if (!password_db.equalsIgnoreCase(password_input_md5)) {//抛出异常throw new CustomException("用户名或密码错误");}//得到用户idString userid = sysUser.getId();//认证通过,返回用户身份信息ActiveUser activeUser = new ActiveUser();activeUser.setUserid(userid);activeUser.setUsercode(usercode);activeUser.setUsername(sysUser.getUsername());return activeUser;}public SysUser findSysUserByUserCode(String userCode) throws Exception {SysUserExample sysUserExample = new SysUserExample();SysUserExample.Criteria criteria = sysUserExample.createCriteria();criteria.andUsercodeEqualTo(userCode);List<SysUser> list = sysUserMapper.selectByExample(sysUserExample);if (list != null && list.size() > 0) {return list.get(0);}return null;}......
}
配置Service,往类Service中使用@Autowire 需要注册Service 注册有两种方法(注解或配置文件),在架构时没有配置扫描Service 需要在配置文件中注册Service
<!-- 认证和授权的Service --><bean id="sysService" class="liuxun.ssm.service.impl.SysServiceImpl"></bean>
controller(记录Session)
//用户登录提交方法@RequestMapping("/login")public String login(HttpSession session,String randomcode,String usercode,String password) throws Exception{// 校验验证码,防止恶性攻击// 从Session中获取正确的验证码String validateCode = (String) session.getAttribute("validateCode");//输入的验证码和Session中的验证码进行对比if (!randomcode.equalsIgnoreCase(validateCode)) {//抛出异常throw new CustomException("验证码输入错误");}//调用Service校验用户账号和密码的正确性ActiveUser activeUser = sysService.authenticat(usercode, password);//如果Service校验通过,将用户身份记录到Sessionsession.setAttribute("activeUser", activeUser);//重定向到商品查询页面return "redirect:/first.action";}
用户认证拦截器
anonymousURL.properties配置匿名URL
编写身份认证拦截器
//用于用户认证校验、用户权限校验@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//得到请求的urlString url = request.getRequestURI();//判断是否是公开地址//实际开发中需要将公开地址配置在配置文件中//从配置文件中取出可以匿名访问的URLList<String> open_urls = ResourcesUtil.getKeyList("anonymousURL");for (String open_url : open_urls) {if (url.indexOf(open_url)>=0) {//如果是公开地址 则放行return true;}}//判断用户身份在Session中是否存在HttpSession session = request.getSession();ActiveUser activeUser = (ActiveUser) session.getAttribute("activeUser");//如果用户身份在session中存在则放行if (activeUser!=null) {return true;}//执行到这里拦截,跳转到登录页面,用户进行身份认证request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);//如果返回false表示拦截器不继续执行handler,如果返回true表示放行return false;}
配置认证拦截器
<!-- 拦截器 --><mvc:interceptors><mvc:interceptor><!-- 用户认证拦截 --><mvc:mapping path="/**"/><bean class="liuxun.ssm.controller.interceptor.LoginInterceptor"></bean></mvc:interceptor></mvc:interceptors>
用户授权
commonURL.properties配置公用访问地址
获取用户权限范围的菜单
public class ActiveUser implements Serializable {private String userid; //用户id(主键)private String usercode; // 用户账号private String username; // 用户姓名private List<SysPermission> menus; //菜单//......setter和getter方法
}
自定义权限Mapper
<!-- 根据用户id查询菜单 -->
<select id="findMenuListByUserId" parameterType="string" resultType="liuxun.ssm.po.SysPermission">SELECT * FROMsys_permission WHERE TYPE = 'menu' AND id IN (SELECT sys_permission_id FROMsys_role_permission WHERE sys_role_id IN (SELECT sys_role_id FROMsys_user_role WHERE sys_user_id = #{userid}))
</select>
在 SysPermissionMapperCustom .java接口中添加对应的方法
public interface SysPermissionMapperCustom {//根据用户id查询菜单public List<SysPermission> findMenuListByUserId(String userid) throws Exception;.......
}
在权限Service接口中添加对应的方法 在实现中注入SysPermissionMapperCustom
@Overridepublic List<SysPermission> findMenuListByUserId(String userid) throws Exception {return sysPermissionMapperCustom.findMenuListByUserId(userid);}
获取用户权限范围的URL
思路:
public class ActiveUser implements Serializable {private String userid; //用户id(主键)private String usercode; // 用户账号private String username; // 用户姓名private List<SysPermission> menus; //菜单private List<SysPermission> permissions; //权限//...setter和getter方法
}
在 SysPermissionMapperCustom .xml中添加根据用户id查询用户权限的URL
<!-- 根据用户id查询URL -->
<select id="findPermissionListByUserId" parameterType="string" resultType="liuxun.ssm.po.SysPermission">SELECT * FROMsys_permission WHERE TYPE = 'permission' AND id IN (SELECT sys_permission_id FROMsys_role_permission WHERE sys_role_id IN (SELECT sys_role_id FROMsys_user_role WHERE sys_user_id = #{userid}))
</select>
//根据用户id查询权限URLpublic List<SysPermission> findPermissionListByUserId(String userid) throws Exception;
SysServiceImpl.java中添加如下内容
@Overridepublic List<SysPermission> findPermissionListByUserId(String userid) throws Exception {return sysPermissionMapperCustom.findPermissionListByUserId(userid);}
用户认证通过后取出菜单和URL放入Session
修改权限SysServiceImpl中用户认证方法的代码
//得到用户idString userid = sysUser.getId();//根据用户id查询菜单List<SysPermission> menus = this.findMenuListByUserId(userid);//根据用户id查询权限urlList<SysPermission> permissions = this.findPermissionListByUserId(userid);//认证通过,返回用户身份信息ActiveUser activeUser = new ActiveUser();activeUser.setUserid(userid);activeUser.setUsercode(usercode);activeUser.setUsername(sysUser.getUsername());//放入权限范围的菜单和urlactiveUser.setMenus(menus);activeUser.setPermissions(permissions);
菜单动态显示
<c:if test="${activeUser.menus!=null }"><ul><c:forEach items="${activeUser.menus }" var="menu"><li><div><a title="${menu.name }" ref="1_1" href="#"rel="${baseurl }/${menu.url }" icon="icon-log"><spanclass="icon icon-log"> </span><span class="nav"><a href=javascript:addTab('${menu.name }','${baseurl }/${menu.url }')>${menu.name }</a></span></a></div></li></c:forEach></ul></c:if>
授权拦截器
public class PermissionInterceptor implements HandlerInterceptor{//在执行handler之前执行的//用于用户认证校验、用户权限校验@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//得到请求的urlString url = request.getRequestURI();//判断是否是公开地址//实际开发中需要将公开地址配置在配置文件中//从配置文件中取出可以匿名访问的URLList<String> open_urls = ResourcesUtil.getKeyList("anonymousURL");for (String open_url : open_urls) {if (url.indexOf(open_url)>=0) {//如果是公开地址 则放行return true;}}//从配置文件中获取公用访问urlList<String> common_urls = ResourcesUtil.getKeyList("commonURL");//遍历公用地址 如果是公开地址则放行for (String common_url : common_urls) {if (url.indexOf(common_url)>0) {//如果是公开,则放行return true;}}//判断用户身份在Session中是否存在HttpSession session = request.getSession();ActiveUser activeUser = (ActiveUser) session.getAttribute("activeUser");//从Session中取出权限范围的URLList<SysPermission> permissions = activeUser.getPermissions();for (SysPermission sysPermission : permissions) {//权限urlString permission_url = sysPermission.getUrl();if (url.indexOf(permission_url)>0) {return true;}}//执行到这里拦截,跳转到无权访问的提示页面request.getRequestDispatcher("/WEB-INF/jsp/refuse.jsp").forward(request, response);//如果返回false表示拦截器不继续执行handler,如果返回true表示放行return false;}......
}
配置授权拦截器
注意:要将授权拦截器配置在用户认证拦截器的下边,这是因为SpringMVC拦截器的放行方法是顺序执行的,如果是Struts的话则正好相反。
<!-- 拦截器 --><mvc:interceptors><mvc:interceptor><!-- 用户认证拦截 --><mvc:mapping path="/**"/><bean class="liuxun.ssm.controller.interceptor.LoginInterceptor"></bean></mvc:interceptor><mvc:interceptor><!-- 资源拦截 --><mvc:mapping path="/**"/><bean class="liuxun.ssm.controller.interceptor.PermissionInterceptor"></bean></mvc:interceptor></mvc:interceptors>
运行测试:
此项目Demo已上传GitHub(https://github.com/LX1993728/permission_web_noshiro)
package liuxun.ssm.po;import java.io.Serializable;
import java.util.List;/*** 用户身份信息,存入Session 由于Tomcat正常关闭时会将Session序列化的本地硬盘上,所以实现Serializable接口* @author liuxun**/
public class ActiveUser implements Serializable {private static final long serialVersionUID = 1L;private String userid; //用户id(主键)private String usercode; // 用户账号private String username; // 用户姓名private List<SysPermission> menus; //菜单private List<SysPermission> permissions; //权限// 提供对应setter和getter方法......
}
自定义权限的Mapper
package liuxun.ssm.mapper;import java.util.List;
import liuxun.ssm.po.SysPermission;
import liuxun.ssm.po.SysPermissionExample;
import org.apache.ibatis.annotations.Param;
/*** 权限mapper* @author liuxun**/
public interface SysPermissionMapperCustom {//根据用户id查询菜单public List<SysPermission> findMenuListByUserId(String userid) throws Exception;//根据用户id查询权限URLpublic List<SysPermission> findPermissionListByUserId(String userid) throws Exception;
}
SysPermissionMapperCustom.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="liuxun.ssm.mapper.SysPermissionMapperCustom"><!-- 根据用户id查询菜单 -->
<select id="findMenuListByUserId" parameterType="string" resultType="liuxun.ssm.po.SysPermission">SELECT * FROMsys_permission WHERE TYPE = 'menu' AND id IN (SELECT sys_permission_id FROMsys_role_permission WHERE sys_role_id IN (SELECT sys_role_id FROMsys_user_role WHERE sys_user_id = #{userid}))
</select>
<!-- 根据用户id查询URL -->
<select id="findPermissionListByUserId" parameterType="string" resultType="liuxun.ssm.po.SysPermission">SELECT * FROMsys_permission WHERE TYPE = 'permission' AND id IN (SELECT sys_permission_id FROMsys_role_permission WHERE sys_role_id IN (SELECT sys_role_id FROMsys_user_role WHERE sys_user_id = #{userid}))
</select>
</mapper>
自定义权限的Service接口以及实现类
package liuxun.ssm.service;import java.util.List;import liuxun.ssm.po.ActiveUser;
import liuxun.ssm.po.SysPermission;
import liuxun.ssm.po.SysUser;/*** 认证授权服务接口* @author liuxun**/
public interface SysService {//根据用户的身份和密码进行认证,如果认证通过,返回用户身份信息public ActiveUser authenticat(String usercode,String password) throws Exception;//根据用户账号查询用户信息public SysUser findSysUserByUserCode(String userCode) throws Exception;//根据用户id查询权限范围内的菜单public List<SysPermission> findMenuListByUserId(String userid) throws Exception;//根据用户id查询权限范围内的urlpublic List<SysPermission> findPermissionListByUserId(String userid) throws Exception;
}
SysServiceImpl.java
package liuxun.ssm.service.impl;import java.util.List;import org.springframework.beans.factory.annotation.Autowired;import liuxun.ssm.exception.CustomException;
import liuxun.ssm.mapper.SysPermissionMapperCustom;
import liuxun.ssm.mapper.SysUserMapper;
import liuxun.ssm.po.ActiveUser;
import liuxun.ssm.po.SysPermission;
import liuxun.ssm.po.SysUser;
import liuxun.ssm.po.SysUserExample;
import liuxun.ssm.service.SysService;
import liuxun.ssm.util.MD5;public class SysServiceImpl implements SysService {@Autowiredprivate SysUserMapper sysUserMapper;@Autowiredprivate SysPermissionMapperCustom sysPermissionMapperCustom;public ActiveUser authenticat(String usercode, String password) throws Exception {/*** 认证过程: 根据用户身份(账号)查询数据库,如果查询不到则用户不存在 * 对输入的密码和数据库密码进行比对,如果一致则认证通过*/// 根据用户账号查询数据库SysUser sysUser = this.findSysUserByUserCode(usercode);if (sysUser == null) {// 抛出异常throw new CustomException("用户账号不存在");}// 数据库密码(MD5加密后的密码)String password_db = sysUser.getPassword();// 对输入的密码和数据库密码进行比对,如果一致,认证通过// 对页面输入的密码进行MD5加密String password_input_md5 = new MD5().getMD5ofStr(password);if (!password_db.equalsIgnoreCase(password_input_md5)) {//抛出异常throw new CustomException("用户名或密码错误");}//得到用户idString userid = sysUser.getId();//根据用户id查询菜单List<SysPermission> menus = this.findMenuListByUserId(userid);//根据用户id查询权限urlList<SysPermission> permissions = this.findPermissionListByUserId(userid);//认证通过,返回用户身份信息ActiveUser activeUser = new ActiveUser();activeUser.setUserid(userid);activeUser.setUsercode(usercode);activeUser.setUsername(sysUser.getUsername());//放入权限范围的菜单和urlactiveUser.setMenus(menus);activeUser.setPermissions(permissions);return activeUser;}public SysUser findSysUserByUserCode(String userCode) throws Exception {SysUserExample sysUserExample = new SysUserExample();SysUserExample.Criteria criteria = sysUserExample.createCriteria();criteria.andUsercodeEqualTo(userCode);List<SysUser> list = sysUserMapper.selectByExample(sysUserExample);if (list != null && list.size() > 0) {return list.get(0);}return null;}@Overridepublic List<SysPermission> findMenuListByUserId(String userid) throws Exception {return sysPermissionMapperCustom.findMenuListByUserId(userid);}@Overridepublic List<SysPermission> findPermissionListByUserId(String userid) throws Exception {return sysPermissionMapperCustom.findPermissionListByUserId(userid);}
}
登录控制器
package liuxun.ssm.controller;import javax.servlet.http.HttpSession;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import liuxun.ssm.exception.CustomException;
import liuxun.ssm.po.ActiveUser;
import liuxun.ssm.service.SysService;/*** 登录和退出* @author liuxun**/
@Controller
public class LoginController {@Autowiredprivate SysService sysService;//用户登录提交方法@RequestMapping("/login")public String login(HttpSession session,String randomcode,String usercode,String password) throws Exception{// 校验验证码,防止恶性攻击// 从Session中获取正确的验证码String validateCode = (String) session.getAttribute("validateCode");//输入的验证码和Session中的验证码进行对比if (!randomcode.equalsIgnoreCase(validateCode)) {//抛出异常throw new CustomException("验证码输入错误");}//调用Service校验用户账号和密码的正确性ActiveUser activeUser = sysService.authenticat(usercode, password);//如果Service校验通过,将用户身份记录到Sessionsession.setAttribute("activeUser", activeUser);//重定向到商品查询页面return "redirect:/first.action";}//用户退出@RequestMapping("/logout")public String logout(HttpSession session) throws Exception{//session失效session.invalidate();//重定向到商品查询页面return "redirect:/first.action";}
}
身份认证拦截器LoginInterceptor.java
package liuxun.ssm.controller.interceptor;import java.util.List;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import liuxun.ssm.po.ActiveUser;
import liuxun.ssm.util.ResourcesUtil;/*** 测试拦截器1* @author liuxun**/
public class LoginInterceptor implements HandlerInterceptor{//在执行handler之前执行的//用于用户认证校验、用户权限校验@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//得到请求的urlString url = request.getRequestURI();//判断是否是公开地址//实际开发中需要将公开地址配置在配置文件中//从配置文件中取出可以匿名访问的URLList<String> open_urls = ResourcesUtil.getKeyList("anonymousURL");for (String open_url : open_urls) {if (url.indexOf(open_url)>=0) {//如果是公开地址 则放行return true;}}//判断用户身份在Session中是否存在HttpSession session = request.getSession();ActiveUser activeUser = (ActiveUser) session.getAttribute("activeUser");//如果用户身份在session中存在则放行if (activeUser!=null) {return true;}//执行到这里拦截,跳转到登录页面,用户进行身份认证request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);//如果返回false表示拦截器不继续执行handler,如果返回true表示放行return false;}//在执行handler返回modelAndView之前执行//如果需要向页面提供一些公用的数据或配置一些视图信息,使用此方法实现 从modelAndView入手@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception {System.out.println("HandlerInterceptor2...postHandle");}//执行handler之后执行此方法//作为系统统一异常处理,进行方法执行性能监控,在preHandler中设置一个时间点 在afterCompletion设置一个时间点 二者时间差就是执行时长//实现系统,统一日志记录@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception modelAndView)throws Exception {System.out.println("HandlerInterceptor2...afterCompletion");}}
资源授权拦截器PermissionInterceptor
package liuxun.ssm.controller.interceptor;import java.security.acl.Permission;
import java.util.List;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import liuxun.ssm.po.ActiveUser;
import liuxun.ssm.po.SysPermission;
import liuxun.ssm.util.ResourcesUtil;/*** 授权拦截器* @author liuxun**/
public class PermissionInterceptor implements HandlerInterceptor{//在执行handler之前执行的//用于用户认证校验、用户权限校验@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//得到请求的urlString url = request.getRequestURI();//判断是否是公开地址//实际开发中需要将公开地址配置在配置文件中//从配置文件中取出可以匿名访问的URLList<String> open_urls = ResourcesUtil.getKeyList("anonymousURL");for (String open_url : open_urls) {if (url.indexOf(open_url)>=0) {//如果是公开地址 则放行return true;}}//从配置文件中获取公用访问urlList<String> common_urls = ResourcesUtil.getKeyList("commonURL");//遍历公用地址 如果是公开地址则放行for (String common_url : common_urls) {if (url.indexOf(common_url)>0) {//如果是公开,则放行return true;}}//判断用户身份在Session中是否存在HttpSession session = request.getSession();ActiveUser activeUser = (ActiveUser) session.getAttribute("activeUser");//从Session中取出权限范围的URLList<SysPermission> permissions = activeUser.getPermissions();for (SysPermission sysPermission : permissions) {//权限urlString permission_url = sysPermission.getUrl();if (url.indexOf(permission_url)>0) {return true;}}//执行到这里拦截,跳转到无权访问的提示页面request.getRequestDispatcher("/WEB-INF/jsp/refuse.jsp").forward(request, response);//如果返回false表示拦截器不继续执行handler,如果返回true表示放行return false;}//在执行handler返回modelAndView之前执行//如果需要向页面提供一些公用的数据或配置一些视图信息,使用此方法实现 从modelAndView入手@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception {System.out.println("HandlerInterceptor2...postHandle");}//执行handler之后执行此方法//作为系统统一异常处理,进行方法执行性能监控,在preHandler中设置一个时间点 在afterCompletion设置一个时间点 二者时间差就是执行时长//实现系统,统一日志记录@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception modelAndView)throws Exception {System.out.println("HandlerInterceptor2...afterCompletion");}}
拦截器配置
<!-- 拦截器 --><mvc:interceptors><mvc:interceptor><!-- 用户认证拦截 --><mvc:mapping path="/**"/><bean class="liuxun.ssm.controller.interceptor.LoginInterceptor"></bean></mvc:interceptor><mvc:interceptor><!-- 资源拦截 --><mvc:mapping path="/**"/><bean class="liuxun.ssm.controller.interceptor.PermissionInterceptor"></bean></mvc:interceptor></mvc:interceptors>
使用URL拦截总结:
JAVAWEB开发之权限管理(一)——权限管理详解(权限管理原理以及方案)、不使用权限框架的原始授权方式详解相关推荐
- JavaWeb开发:Excel文件上传、解析、过滤,并存入数据库(基于SSM框架)
目录 一.效果展示 1.初始状态 2.导入的Excel文件 3.导入后状态 4.文件信息过滤更新 二.实现 1.文件传递 2.Controller层 3.Service层 4.ServiceImple ...
- linux设置共享权限设置命令,Linux系列知识详解(三)--------- Linux链接命令和权限管理命令...
Linux系列知识详解(三)--------- Linux链接命令和权限管理命令 一:链接命令ln 简介:什么是链接命令?链接命令分为软链接和硬链接.其中软链接产生的新文件是以路径的形式表示原文件,类 ...
- 企业办公oa系统、医药OA办公后台管理、会议管理、用户管理、物料管理、活动管理、日常拜访、Axure医药内部管理平台、web端后台管理系统原型、医药OA系统、权限管理、Axure原型、rp原型
企业办公oa系统.医药OA办公后台管理.会议管理.用户管理.物料管理.活动管理.Axure医药内部管理平台.web端后台管理系统原型.医药OA系统.权限管理 Axure原型演示及下载地址:https: ...
- Linux 学习笔记3 权限管理 定时任务 网络配置 进程、软件包管理
权限管理 linux组的介绍 在linux中的每个用户必须属于一个组,不能独立于组外.在linux中每个文件有所有者.所在组.其它组的概念. 1.所有者 2.所在组 3.其它组 4.改变用户所在的组 ...
- JAVAWEB开发之工作流详解(二)——Activiti核心API的使用(流程定义和流程实例的管理、流程变量、监听器...)以及与Spring的集成
管理流程定义 设计流程定义文档 bpmn文件 设置方式可以直接使用插件图形化界面进行设置 为某任务节点指定任务执行者 保存后的BPMN文件可以使用XML编辑器打开 BPMN 2.0根节点是defini ...
- java开发底薪加绩效代码,基于jsp的员工绩效管理-JavaEE实现员工绩效管理 - java项目源码...
基于jsp+servlet+pojo+mysql实现一个javaee/javaweb的员工绩效管理, 该项目可用各类java课程设计大作业中, 员工绩效管理的系统架构分为前后台两部分, 最终实现在线上 ...
- python开发企业管理平台_我的第一个python web开发框架(34)——后台管理系统权限设计...
框架底层和接口终于改造完成了,小白再次找到老菜. 小白:老大,上次你对后台权限系统简单的讲了一下,我一点头绪都没有,现在有空完整的说一说吗? 老菜:说到权限系统,要讲明白真不容易,权限系统并不是越复杂 ...
- C#开发微信门户及应用(27)-公众号模板消息管理
原文:C#开发微信门户及应用(27)-公众号模板消息管理 通过模板消息接口,公众号能向关注其账号的用户发送预设模板的消息.模板消息仅用于公众号向用户发送重要的服务通知,只能用于符合其要求的服务场景中, ...
- 企业微信开发实战(四、OA审批之企业假期管理配置、获取成员假期余额、修改成员假期余额)
文章目录 7.获取企业假期管理配置 7.1概述 7.2代码实战 8.获取成员假期余额 8.1概述 8.2代码实战 8.3试错 9.修改成员假期余额 9.1概述 9.2代码实战 9.3试错 源码 赞赏 ...
最新文章
- PHP+socket+SMTP、POP3协议发送、接收邮件
- 商汤科技宣布C轮战略融资6亿美元 阿里领投苏宁跟投
- oracle错误12518,ORA-12518: 错误 客户端连接不上
- 传统的6d位姿估计fangfa1_你的厨房被水淹了!别担心,这只是3D深度估计做出的特效...
- 最像windows10的linux,Linuxfx:外观神似Win10的Linux操作系统
- vue报错vue-router.esm.js?8c4f:2062 Uncaught (in promise) Error: Avoided redundant navigation to curren
- html5 百度地图api文档,开发指南--百度地图JavaScript API大众版.doc
- 动态修改attr里的多个属性
- 数学建模算法与应用_《数学建模算法与应用》笔记【1】
- 装饰模式-包装request和response
- jstree禁用父节点点击_Jstree 使用CheckBox插件 选中父节点时被禁用的子节点也会选中问题...
- java常用的库_java有哪些常用的库
- 病毒软件诈骗帝国 恐惧心理刺激销售
- 【架构师实践课】单体和微服务怎么选?单体到微服务怎么转?
- 海归学子创新创业座谈会:龙凡教授向浙江省委书记车俊汇报 Conflux 研发进展...
- echarts 环形图 不同区域背景色自定义
- Python就业都有哪些岗位?
- MySQL:一主两从架构(读写分离)
- Python从入门到精通--课程目录
- Grafana 介绍和使用