一、实现原理

1.实现原理

  本示例采用SpringMVC的拦截器来实现一个基于URL的权限拦截。

2.权限管理流程

二、数据库搭建

1.用户表(sys_user)

(1)表结构



(2)表字段说明

 id:主键

 usercode:登录用户名

 username:姓名

 passsword:密码

 salt:盐

 locked:是否锁定

(3)表数据

INSERT INTO `sys_user` VALUES ('lisi', 'lisi', '李四', '96e79218965eb72c92a549dd5a330112', 'uiwueylm', '0');
INSERT INTO `sys_user` VALUES ('zhangsan', 'zhangsan', '张三', '96e79218965eb72c92a549dd5a330112', 'eteokues', '0');

2.角色表(sys_role)

(1)表结构



(2)表字段说明

 id:主键

 name:角色名称

 avaliable:是否启用

(3)表数据

INSERT INTO `sys_role` VALUES ('ebc8a441-c6f9-11e4-b137-0adc305c3f28', '商品管理员', '1');
INSERT INTO `sys_role` VALUES ('ebc9d647-c6f9-11e4-b137-0adc305c3f28', '用户管理员', '1');

3.权限表(sys_premission)

(1)表结构



(2)表字段说明

 id:主键

 name:资源名称

 type:资源类型

 url:访问url地址

 percode:权限代码字符串

 parentid:父结点id

 parentids:父结点id列表串

 sortstring:排序号

 available:是否启用

(3)表数据

INSERT INTO `sys_permission` VALUES ('1', '权限', '', '', null, '0', '0/', '0', '1');
INSERT INTO `sys_permission` VALUES ('11', '商品管理', 'menu', 'queryItems.action', null, '1', '0/1/', '1.', '1');
INSERT INTO `sys_permission` VALUES ('12', '商品新增', 'permission', '/item/add.action', 'item:create', '11', '0/1/11/', '', '1');
INSERT INTO `sys_permission` VALUES ('13', '商品修改', 'permission', '/updateitems.action', 'item:update', '11', '0/1/11/', '', '1');
INSERT INTO `sys_permission` VALUES ('14', '商品删除', 'permission', '', 'item:delete', '11', '0/1/11/', '', '1');
INSERT INTO `sys_permission` VALUES ('15', '商品查询', 'permission', '/queryItems.action', 'item:query', '11', '0/1/11/', null, '1');
INSERT INTO `sys_permission` VALUES ('21', '用户管理', 'menu', '/user/query.action', 'user:query', '1', '0/1/', '2.', '1');
INSERT INTO `sys_permission` VALUES ('22', '用户新增', 'permission', '', 'user:create', '21', '0/1/21/', '', '1');
INSERT INTO `sys_permission` VALUES ('23', '用户修改', 'permission', '', 'user:update', '21', '0/1/21/', '', '1');
INSERT INTO `sys_permission` VALUES ('24', '用户删除', 'permission', '', 'user:delete', '21', '0/1/21/', '', '1');

4.用户角色表(sys_user_role)

(1)表结构



(2)表字段说明

 id:主键

 sys_user_id:用户id

 sys_role_id:角色id

(3)表数据

INSERT INTO `sys_user_role` VALUES ('ebc8a441-c6f9-11e4-b137-0adc305c3f28', 'zhangsan', 'ebc8a441-c6f9-11e4-b137-0adc305c');
INSERT INTO `sys_user_role` VALUES ('ebc9d647-c6f9-11e4-b137-0adc305c3f28', 'lisi', 'ebc9d647-c6f9-11e4-b137-0adc305c');

5.角色权限表(sys_role_premission)

(1)表结构



(2)表字段说明

 id:主键

 sys_permission_id:权限id

 sys_role_id:角色id

(3)表数据

INSERT INTO `sys_role_permission` VALUES ('ebc8a441-c6f9-11e4-b137-0adc305c3f21', 'ebc8a441-c6f9-11e4-b137-0adc305c', '12');
INSERT INTO `sys_role_permission` VALUES ('ebc8a441-c6f9-11e4-b137-0adc305c3f22', 'ebc8a441-c6f9-11e4-b137-0adc305c', '11');
INSERT INTO `sys_role_permission` VALUES ('ebc8a441-c6f9-11e4-b137-0adc305c3f24', 'ebc9d647-c6f9-11e4-b137-0adc305c', '21');
INSERT INTO `sys_role_permission` VALUES ('ebc8a441-c6f9-11e4-b137-0adc305c3f25', 'ebc8a441-c6f9-11e4-b137-0adc305c', '15');
INSERT INTO `sys_role_permission` VALUES ('ebc9d647-c6f9-11e4-b137-0adc305c3f23', 'ebc9d647-c6f9-11e4-b137-0adc305c', '22');
INSERT INTO `sys_role_permission` VALUES ('ebc9d647-c6f9-11e4-b137-0adc305c3f26', 'ebc8a441-c6f9-11e4-b137-0adc305c', '13');

6.商品表(items)

(1)表结构



(2)表字段说明

 id:主键

 name:商品名称

 price:商品价格

 detil:商品描述

 pic:商品图片url

 createtime:创建时间

(3)表数据

INSERT INTO `items` VALUES ('1', '台式机', '3000.0', '该电脑质量非常好!!!!', null, '2015-02-03 13:22:53');
INSERT INTO `items` VALUES ('2', '笔记本', '6000.0', '笔记本性能好,质量好!!!!!', null, '2015-02-09 13:22:57');
INSERT INTO `items` VALUES ('3', '背包', '200.0', '名牌背包,容量大质量好!!!!', null, '2015-02-06 13:23:02');

三、程序实现

(一)认证

1.系统登录流程

  系统 登陆相当 于用户身份认证,用户成功,要在session中记录用户的身份信息.

  操作流程:

    1. 用户进行登陆页面

    2. 输入用户名和密码进行登陆

    3. 进行用户名和密码校验

    4. 如果校验通过,在session记录用户身份信息

2.创建专门类用于记录用户身份信息

 public class ActiveUser {
//用户id
private String userid;
//用户账号
private String usercode;
//用户名称
private String username;
//getter and setter....
}

3.mybatis的mapper和mapper接口

(1)ActiveUserMapper.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="com.jack.mapper.ActiveUserMapper"> <select id="authenticat" parameterType="String" resultType="activeUser" >
SELECT * FROM sys_user WHERE usercode = #{id}
</select>
</mapper>

(2)ActiveUserMapper.java

public interface ActiveUserMapper {

    public ActiveUser authenticat(String usercode) throws Exception;
}

4.service(进行用户名和密码校验)

public interface UserService {
//根据用户名和密码进行身份验证,如果通过,则返回身份信息
public ActiveUser authenticat(String usercode, String password) throws Exception;
}

5.验证的实现类

 public ActiveUser authenticat(String usercode, String password) throws Exception {

        //查询该用户
User user = userMapper.authenticat(usercode); if(user == null){
throw new ItemsException("该账号不存在");
}
//得到用户的id
String userid = user.getId();
//获取该用户的密码
String user_password = user.getPassword();
MD5 md5 = new MD5();
String passwprd1 = md5.getMD5ofStr(password);
//将密码和输入的密码进行比较
if(!user_password.equals(passwprd1)){
throw new ItemsException("用户名或密码错误");
}
//认证通过,返回认证信息
ActiveUser activeUser = new ActiveUser();
activeUser.setUsercode(user.getUsercode());
activeUser.setUsername(user.getUsername());
activeUser.setUserid(user.getId());
return activeUser;
}

6.controller

   /**
* TODO:登录controller
* @param session 系统session
* @param randomcode 验证码
* @param usercode 用户账号
* @param password //用户密码
* @return 重定向
* @throws Exception
*/
@RequestMapping("/login")
public String login (HttpSession session,String randomcode,String usercode,String password)throws Exception{
//从session中获取验证码信息
String validateCode = (String) session.getAttribute("validateCode");
//对比验证码信息
/* if(!validateCode.equals(randomcode)){
//验证码不一致,抛出异常
throw new ItemsException("验证码错误");
}*/
//检验账号密码是否正确
ActiveUser activeUser = userService.authenticat(usercode,password);
//将身份信息保存到session
session.setAttribute("activeUser",activeUser);
return "redirect:/first.action";
}

7.创建保存匿名访问地址的properties文件

#可以匿名访问的url地址
login.action = 登录

8.编写登录的拦截器LoginIntersector

public class LoginIntersector implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { //得到请求的URL
String url = httpServletRequest.getRequestURI();
//判断是否是公开地址
//1.从配置文件中获取全部公开地址
List<String> anonymousUrl = ResourcesUtil.gekeyList("./config/anonymousURL");
//对比URL
for (String an_url: anonymousUrl) {
if(url.indexOf(an_url) >= 0){
//如果是公开地址,放行
return true;
}
}
//获取session
HttpSession session = httpServletRequest.getSession();
//获取身份信息
ActiveUser activeUser = (ActiveUser) session.getAttribute("activeUser");
//判断身份信息在session中是否存在
if(activeUser != null){
//存在放行
return true;
}
//跳转到登录页面
httpServletRequest.getRequestDispatcher("/page/login.jsp").forward(httpServletRequest,httpServletResponse);
return false;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { }
}

9.配置登录的拦截器

 <!--配置全局的拦截器-->
<mvc:interceptors>
<!--多个拦截器顺序执行-->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.jack.intersector.LoginIntersector" />
</mvc:interceptor>
</mvc:interceptors>

(二)、授权

1.流程

在用户认证时,认证通过,根据用户id从数据库获取用户权限范围的菜单,将菜单的集合存储在session中。

2.修改用于记录用户身份信息的类

public class ActiveUser {
//用户id
private String userid;
//用户账号
private String usercode;
//用户名称
private String username;
//用户权限列表
private List<SysPermission> menus;
//用户菜单列表
private List<SysPermission> permissions;

3.mapper和mapper接口

(1) SyspermissionMapper.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="com.jack.mapper.SyspermissionMapper"> <select id="findMenuListByUserId" parameterType="String" resultType="sysPermission">
SELECT
*
FROM
sys_permission
WHERE
type = 'menu'
AND
id IN (
SELECT
sys_permission_id
FROM
sys_role_permission
WHERE
sys_role_id IN (
SELECT
sys_role_id
FROM
sys_user_role
WHERE
sys_user_id =#{id}
)
)
</select> <select id="findPermissionListByUserId" parameterType="String" resultType="sysPermission">
SELECT
*
FROM
sys_permission
WHERE
type = 'permission'
AND
id IN (
SELECT
sys_permission_id
FROM
sys_role_permission
WHERE
sys_role_id IN (
SELECT
sys_role_id
FROM
sys_user_role
WHERE
sys_user_id =#{id}
)
)
</select>
</mapper>

(2)SyspermissionMapper.java

public interface SyspermissionMapper {

    //获取用户的权限列表
public List<SysPermission> findPermissionListByUserId(String userid) throws Exception;
//获取用户的菜单列表
public List<SysPermission> findMenuListByUserId(String userid) throws Exception;
}

(4)修改service接口实现类

  public ActiveUser authenticat(String usercode, String password) throws Exception {

        //查询该用户
User user = userMapper.authenticat(usercode); if(user == null){
throw new ItemsException("该账号不存在");
}
//等到用户的id
String userid = user.getId();
//得到用户的菜单列表
List<SysPermission> menus = syspermissionMapper.findMenuListByUserId(userid);
//得到用户的权限列表
List<SysPermission> permissions = syspermissionMapper.findPermissionListByUserId(userid);
//获取该用户的密码
String user_password = user.getPassword();
MD5 md5 = new MD5();
String passwprd1 = md5.getMD5ofStr(password);
//将密码和输入的密码进行比较
if(!user_password.equals(passwprd1)){
throw new ItemsException("用户名或密码错误");
}
//认证通过,返回认证信息
ActiveUser activeUser = new ActiveUser();
activeUser.setUsercode(user.getUsercode());
activeUser.setUsername(user.getUsername());
activeUser.setUserid(user.getId());
activeUser.setMenus(menus);
activeUser.setPermissions(permissions);
return activeUser;
}

(5)页面菜单的动态显示

   <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"><span
class="icon icon-log">&nbsp;</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>

(6)权限拦截器PermissionIntersector

public class PermissionIntersector implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { //得到用户的访问地址
String url1 = httpServletRequest.getRequestURI();
String url = url1.substring(url1.lastIndexOf("/"));
//判断是否是公开地址
List<String> an_urls = ResourcesUtil.gekeyList("./config/anonymousURL");
for (String an_url:an_urls) {
if(url.indexOf(an_url) >=0){
return true;
}
}
//判读是否是共用地址
List<String> co_urls = ResourcesUtil.gekeyList("./config/commonURL");
for (String co_url: co_urls) {
if(url.indexOf(co_url) >= 0){
return true;
}
} //获取session
HttpSession session = httpServletRequest.getSession();
//获得权限列表
ActiveUser activeUser = (ActiveUser) session.getAttribute("activeUser");
//获取权限列表
List<SysPermission> permissions = activeUser.getPermissions();
for (SysPermission permission:permissions
) {
String p_url = permission.getUrl();
if(url.indexOf(p_url) >= 0){
return true;
}
}
httpServletRequest.getRequestDispatcher("page/refuse.jsp").forward(httpServletRequest,httpServletResponse);
return false;
} @Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { }
}

(7)配置权限拦截器

 <!--配置全局的拦截器-->
<mvc:interceptors>
<!--多个拦截器顺序执行-->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.jack.intersector.LoginIntersector" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.jack.intersector.PermissionIntersector" />
</mvc:interceptor>
</mvc:interceptors>

四、总结

使用基于url拦截的权限管理方式,实现起来比较简单,不依赖框架,使用web提供filter就可以实现。

问题:

需要将所有的url全部配置起来,有些繁琐,不易维护,url(资源)和权限表示方式不规范。

基于URL权限拦截的实现的更多相关文章

  1. spring security实现简单的url权限拦截

    在一个系统中,权限的拦截是很常见的事情,通常情况下我们都是基于url进行拦截.那么在spring security中应该怎么配置呢. 大致步骤如下: 1.用户登录成功后我们需要拿到用户所拥有的权限,并 ...

  2. Shiro集成SSM基于URL权限管理(一)

    学习了shiro之后,我们就可以说尝试把shiro加入ssm中,并做一套基于URL的权限管理. 其他的准备工作就不多说了,直接动手操作,看到效果再去理解. 表结构 执行如下,数据库名字可以自行修改,不 ...

  3. 【基于url权限管理 shiro(一)】--基础

    只要有用户参与的系统一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源.权限管理包括用户认证和授权两部分.   用户认证 1.概 ...

  4. 基于url的权限管理

    基于url权限管理流程 完成权限管理的数据模型创建. 1.     系统登陆 系统 登陆相当 于用户身份认证,用户成功,要在session中记录用户的身份信息. 操作流程: 用户进行登陆页面 输入用户 ...

  5. Shiro集成SSM基于动态URL权限管理(二)

    这个案例基于上一个demo扩展而来.所以数据库表,在Shiro集成SSM基于URL权限管理(一)开篇的一致.如果上个demo操作的建议重新导入一次,避免出现问题. 而这次都不是通过固定写在方法上的注解 ...

  6. 基于 URL 的权限控制

    先不用框架,自己实现一下 数据库 /* SQLyog v10.2 MySQL - 5.1.72-community : Database - shiro *********************** ...

  7. 基于url拦截实现权限控制

    用户表,角色表,用户角色表,权限表,权限角色表 1.用户通过认证(可以是验证用户名,密码等) 2.登陆拦截器,为公开的url放行, 登陆时,将用户信息放入session中,获得用户的权限集合,将集合放 ...

  8. shiro-5基于url的权限管理

    1.1 搭建环境 1.1.1 数据库 mysql5.1数据库中创建表:用户表.角色表.权限表(实质上是权限和资源的结合 ).用户角色表.角色权限表. 完成权限管理的数据模型创建. 1.1.2 开发环境 ...

  9. springboot整合security实现基于url的权限控制

    权限控制基本上是任何一个web项目都要有的,为此spring为我们提供security模块来实现权限控制,网上找了很多资料,但是提供的demo代码都不能完全满足我的需求,因此自己整理了一版. 在上代码 ...

随机推荐

  1. 零成本实现WEB性能测试(二)JMeter基础知识

    特点: 支持多种服务类型进行测试,包括: Web-Http,HTTPS SOAP Database via JDBC LDAP JMS Mail-POP3 & IMAP 支持录制回放方式获取脚 ...

  2. C# 代码 获取桌面路径

    Environment.GetFolderPath(Environment.SpecialFolder.MyComputer); // // 摘要: // 获取由指定枚举标识的系统特殊文件夹的路径. ...

  3. 如何安全地运行用户的 JavaScript 脚本

    本文来自网易云社区,转载务必请注明出处. 有时候我们需要运行用户输入的 JavaScript 脚本(以下简称脚本).对于我们来说,这些脚本是不可信任的,如果在当前的 Context 中运行这些脚本,它 ...

  4. Hadoop完全分布式搭建全过程

    本次操作共4台虚拟机(node211,node212,node213,node214),node211为NameNode,其余3台为DataNode,SecondaryNamenode为node212 ...

  5. ArchLinux下shadow服务报错

    用着Linux蓦然开机就报错了.我是个对报错很敏感的,而是是开机报错. 这个的严重性,听一位前辈说过:如果开机报错你都不理它,慢慢的它就会宕机. 报错内容: shadow服务是Linux下用于校队pa ...

  6. jquery加载方式,选择器,样式操作

    原生js和css不兼容,jquery已经过测试,可放心使用 https://code.jquery.com   这个网站可以下载jquery的源码,比如把源码下载到js文件夹中,文件名为jquery- ...

  7. awk常用用法

    一. 基本使用方法: awk '{pattern + action}' filenames #其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列 ...

  8. UIResponder笔记

    UIResponder是什么 可以响应UIEvent的类,是UIApplication, UIView及UIViewController的父类.它的父类是NSObject 管理第一响应者. 是否是第一 ...

  9. gdb调试参数

    参考 这里 1)gdb 打印字符串的全部内容 set print element 0 2)用x命令查看内存(examine的缩写) (gdb) x/1ub 0x7ffff7fbf7a00x7ffff7 ...

  10. CF960G Bandit Blues 分治+NTT(第一类斯特林数)

    $ \color{#0066ff}{ 题目描述 }$ 给你三个正整数 \(n\),\(a\),\(b\),定义 \(A\) 为一个排列中是前缀最大值的数的个数,定义 \(B\) 为一个排列中是后缀最大 ...