一、基于url权限管理流程【实现步骤】

  基于url拦截是企业中常用的权限管理方法,实现思路是:将系统操作的每个url配置在权限表中,将权限对应到角色,将角色分配给用户,用户访问系统功能通过Filter进行过虑,过虑器获取到用户访问的url,只要访问的url是用户分配角色中的url则放行继续访问。

二、环境搭建以及核心代码

https://github.com/bjlhx15/shiro.git

1、数据库

2、开发环境

3、系统工程框架

三、开发过程步骤

1、系统登录

主要功能:登录、记录用户session【包含用户信息,菜单信息,授权信息】

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

  1.2、操作流程:

         用户进行登陆页面

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

  进行用户名和密码校验

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

    根据用户信息记录菜单menus【用于功能菜单展示】,记录权限资源permissions【用户判断功能项】,一起放到session中

  1.3、激活用户基础类

public class ActiveUser implements java.io.Serializable {
private String userid;//用户id(主键)
private String usercode;// 用户账号
private String username;// 用户名称 private List<SysPermission> menus;// 菜单
private List<SysPermission> permissions;// 权限 public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getUsercode() {
return usercode;
} public void setUsercode(String usercode) {
this.usercode = usercode;
} public String getUserid() {
return userid;
} public void setUserid(String userid) {
this.userid = userid;
} public List<SysPermission> getMenus() {
return menus;
} public void setMenus(List<SysPermission> menus) {
this.menus = menus;
} public List<SysPermission> getPermissions() {
return permissions;
} public void setPermissions(List<SysPermission> permissions) {
this.permissions = permissions;
} }

  1.4、mapperr接口: 根据用户账号查询用户(sys_user)信息(使用逆向工程生成的mapper)

    使用逆向工程生成以下表的基础代码:

      

  1.5、service(进行用户名和密码校验)

    接口功能:根据用户的身份和密码 进行认证,如果认证通过,返回用户身份信息

    认证过程:

      根据用户身份(账号)查询数据库,如果查询不到用户不存在

      对输入的密码 和数据库密码 进行比对,如果一致,认证通过

    

  1.6、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.equals(validateCode)){
//抛出异常
throw new CustomException("验证码输入错误");
} //调用service校验用户账号和密码的正确性
ActiveUser activeUser = sysService.authenticat(usercode, password); //如果service校验通过,将用户身份记录到session
session.setAttribute("activeUser", activeUser);
//重定向到商品查询页面
return "redirect:/first.action";
}

2、用户认证拦截

主要功能:放行匿名url、判断用户session是否存在

2.1、配置匿名访问url【anonymousURL.properties】

  

#配置逆向访问的url
login.action=用户登陆

2.2、编写认证拦截器

  用于用户认证校验、用户权限校验

package com.lhx.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 com.lhx.ssm.po.ActiveUser;
import com.lhx.ssm.util.ResourcesUtil; /**
*
* <p>Title: HandlerInterceptor1</p>
* <p>Description: 用户身份认证拦截器</p>
* @version 1.0
*/
public class LoginInterceptor implements HandlerInterceptor { //在执行handler之前来执行的
//用于用户认证校验、用户权限校验
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception { //得到请求的url
String url = request.getRequestURI(); //判断是否是公开 地址
//实际开发中需要公开 地址配置在配置文件中
//从配置中取逆名访问url List<String> open_urls = ResourcesUtil.gekeyList("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入手
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("HandlerInterceptor1...postHandle"); }
//执行handler之后执行此方法
//作系统 统一异常处理,进行方法执行性能监控,在preHandle中设置一个时间点,在afterCompletion设置一个时间,两个时间点的差就是执行时长
//实现 系统 统一日志记录
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("HandlerInterceptor1...afterCompletion");
} }

2.3、配置拦截器

  在springmvc.xml中配置拦截器:  

    <!--拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 用户认证拦截 -->
<mvc:mapping path="/**" />
<bean class="com.lhx.ssm.controller.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>

3、授权

主要功能:放行匿名url、放行公共、获取用户session,授权资源判断

3.1、公共访问地址【commonURL.properties】

  在此配置文件配置公用访问地址,公用访问地址只要通过用户认证,不需要对公用访问地址分配权限即可访问。

#配置公用的访问地址
first.action=系统首页
logout.action=退出

3.2、获取用户权限范围菜单

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

  po在三中的1.3已添加menus等属性

  mapper xml

    <!-- 根据用户id查询菜单 -->
<select id="findMenuListByUserId" parameterType="string"
resultType="com.lhx.ssm.po.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>

  mapper接口

    //根据用户id查询菜单
public List<SysPermission> findMenuListByUserId(String userid)throws Exception;

  service接口:根据用户id查询用户权限的菜单

    @Override
public List<SysPermission> findMenuListByUserId(String userid)
throws Exception {
return sysPermissionMapperCustom.findMenuListByUserId(userid);
}

3.3、获取用户权限范围的url

  思路:在用户认证时,认证通过,根据用户id从数据库获取用户权限范围的url,将url的集合存储在session中。
  po在三中的1.3已添加permissions等属性

  mapper xml

    <!-- 根据用户id查询url -->
<select id="findPermissionListByUserId" parameterType="string"
resultType="com.lhx.ssm.po.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接口

//根据用户id查询权限url
public List<SysPermission> findPermissionListByUserId(String userid)throws Exception;

  service接口:根据用户id查询用户权限的菜单

    @Override
public List<SysPermission> findPermissionListByUserId(String userid)
throws Exception {
return sysPermissionMapperCustom.findPermissionListByUserId(userid);
}

3.4、用户认证通过后取出菜单和url放入ActiveUser,进而放入session

这里是三中的1.5 完善实现

package com.lhx.ssm.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import com.lhx.ssm.exception.CustomException;
import com.lhx.ssm.mapper.SysPermissionMapperCustom;
import com.lhx.ssm.mapper.SysUserMapper;
import com.lhx.ssm.po.ActiveUser;
import com.lhx.ssm.po.SysPermission;
import com.lhx.ssm.po.SysUser;
import com.lhx.ssm.po.SysUserExample;
import com.lhx.ssm.service.SysService;
import com.lhx.ssm.util.MD5; /**
*
* <p>Title: SysServiceImpl</p>
* <p>Description:认证和授权的服务接口 </p>
* @version 1.0
*/
public class SysServiceImpl implements SysService { @Autowired
private SysUserMapper sysUserMapper; @Autowired
private SysPermissionMapperCustom sysPermissionMapperCustom; @Override
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_input_md5.equalsIgnoreCase(password_db)){
//抛出异常
throw new CustomException("用户名或密码 错误");
}
//得到用户id
String userid = sysUser.getId();
//根据用户id查询菜单
List<SysPermission> menus =this.findMenuListByUserId(userid); //根据用户id查询权限url
List<SysPermission> permissions = this.findPermissionListByUserId(userid); //认证通过,返回用户身份信息
ActiveUser activeUser = new ActiveUser();
activeUser.setUserid(sysUser.getId());
activeUser.setUsercode(userCode);
activeUser.setUsername(sysUser.getUsername());//用户名称 //放入权限范围的菜单和url
activeUser.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()==1){
return list.get(0);
} return null;
} @Override
public List<SysPermission> findMenuListByUserId(String userid)
throws Exception {
return sysPermissionMapperCustom.findMenuListByUserId(userid);
} @Override
public List<SysPermission> findPermissionListByUserId(String userid)
throws Exception { return sysPermissionMapperCustom.findPermissionListByUserId(userid);
} }

3.5、菜单的动态显示需要前端配合

3.6、完整的授权拦截器代码【PermissionInterceptor】

package com.lhx.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 com.lhx.ssm.po.ActiveUser;
import com.lhx.ssm.po.SysPermission;
import com.lhx.ssm.util.ResourcesUtil; /**
*
* <p>Title: PermissionInterceptor</p>
* <p>Description: 授权拦截器</p>
* @version 1.0
*/
public class PermissionInterceptor implements HandlerInterceptor { //在执行handler之前来执行的
//用于用户认证校验、用户权限校验
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception { //得到请求的url
String url = request.getRequestURI(); //判断是否是公开 地址
//实际开发中需要公开 地址配置在配置文件中 //1.从配置中取逆名访问url
List<String> open_urls = ResourcesUtil.gekeyList("anonymousURL");
//遍历公开 地址,如果是公开 地址则放行
for(String open_url:open_urls){
if(url.indexOf(open_url)>=0){
//如果是公开 地址则放行
return true;
}
} //2.从配置文件中获取公共访问地址
List<String> common_urls = ResourcesUtil.gekeyList("commonURL");
//遍历公用 地址,如果是公用 地址则放行
for(String common_url:common_urls){
if(url.indexOf(common_url)>=0){
//如果是公开 地址则放行
return true;
}
} //3.获取session
HttpSession session = request.getSession();
ActiveUser activeUser = (ActiveUser) session.getAttribute("activeUser");
//从session中取权限范围的url
List<SysPermission> permissions = activeUser.getPermissions();
for(SysPermission sysPermission:permissions){
//权限的url
String permission_url = sysPermission.getUrl();
if(url.indexOf(permission_url)>=0){
//如果是权限的url 地址则放行
return true;
}
} //4.执行到这里拦截,跳转到无权访问的提示页面
request.getRequestDispatcher("/WEB-INF/jsp/refuse.jsp").forward(request, response); //如果返回false表示拦截不继续执行handler,如果返回true表示放行
return false;
}
//在执行handler返回modelAndView之前来执行
//如果需要向页面提供一些公用 的数据或配置一些视图信息,使用此方法实现 从modelAndView入手
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("HandlerInterceptor1...postHandle"); }
//执行handler之后执行此方法
//作系统 统一异常处理,进行方法执行性能监控,在preHandle中设置一个时间点,在afterCompletion设置一个时间,两个时间点的差就是执行时长
//实现 系统 统一日志记录
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("HandlerInterceptor1...afterCompletion");
} }

3.7、配置授权拦截器

注意:将授权拦截器配置在用户认证拦截的下边。

    <!--拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 用户认证拦截 -->
<mvc:mapping path="/**" />
<bean class="com.lhx.ssm.controller.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<!-- 授权拦截 -->
<mvc:mapping path="/**" />
<bean class="com.lhx.ssm.controller.interceptor.PermissionInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>

四、小结

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

问题:

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

  如果漏配置,就会无权访问。

  URL也是一种资源

003-基于URL的权限管理[不使用shiro]的更多相关文章

  1. 基于url的权限管理

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

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

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

  3. 基于URL的权限管理(三)

    思路:先创建一个专门的类ActiveUser用于存储用户登录的信息,主要用于存储用户id,账户,名称,菜单,权限. 认证拦截器主要是查看用户是否已登陆,如果没有转发到登陆界面,用户用账户跟密码登录时候 ...

  4. 【shiro】(2)---基于RUL的权限管理

    基于RUL的权限管理 我想在写shiro权限管理认证前,先来一个基于URL实现的权限管理控制. 一.基于URI的权限业务逻辑  实现思路:       将系统操作的每个url配置在权限表中,将权限对应 ...

  5. 基于DDDLite的权限管理OpenAuth.net 1.0版正式发布

    距离上一篇OpenAuth.net的文章已经有5个多月了,在这段时间里项目得到了很多朋友的认可,开源中国上面的Star数接近300,于是坚定了我做下去的信心.最近稍微清闲点,正式推出1.0版,并在阿里 ...

  6. 在ASP.NET MVC中实现基于URL的权限控制

    本示例演示了在ASP.NET MVC中进行基于URL的权限控制,由于是基于URL进行控制的,所以只能精确到页.这种权限控制的优点是可以在已有的项目上改动极少的代码来增加权限控制功能,和项目本身的耦合度 ...

  7. 10.spring-boot基于角色的权限管理页面实现

    10.spring-boot基于角色的权限管理页面实现

  8. 基于云端的通用权限管理系统,SAAS服务,基于SAAS的权限管理,基于SAAS的单点登录SSO,企业单点登录,企业系统监控,企业授权认证中心

    基于云端的通用权限管理系统 SAAS服务 基于SAAS的权限管理 基于SAAS的单点登录SSO 基于.Net的SSO,单点登录系统,提供SAAS服务 基于Extjs 4.2 的企业信息管理系统 基于E ...

  9. devops-jenkins基于角色的权限管理RBAC

    一. devops-jenkins基于角色的权限管理RBAC 1 安装角色的rbac角色管理  1.1) 点击系统管理 1.2) 选择插件管理 1.3) 选择可选插件,输入role搜索 1.4) 选择 ...

随机推荐

  1. HTTP Range header

    http://stackoverflow.com/questions/3303029/http-range-header *************************** 58 down vot ...

  2. 做过的自定义 View

    做过的自定义 View android view custom 音频条状图 需求 详细设计 具体实现 音频条状图 需求 音频图 最终效果类似于音频图中的条状图 只是效果模拟,并不监听真实的音频 条的宽 ...

  3. SlidingMenu.jar 抽屉使用,避免了使用libaray的不兼容的尴尬

         尽管说这个东西出来了一段时间了,可是好东西还是要分享一下的. 之前我们使用的都是libaray.各种出错.团队开发也不好操作.不知道 哪个好心人干脆把这个工具封装成一个jar,真心为你点赞. ...

  4. PHP从千千静听服务器获取lrc歌词

    <?php //转载请注明出处 uenucom function SingleDecToHex($dec)  {  $tmp="";  $dec=$dec%16;  if($ ...

  5. 查看网络连接数目(解决TIME_WAIT过多造成的问题_转)

      转自:解决TIME_WAIT过多造成的问题 (eroswang的csdn) #netstat -n | awk '/^tcp/ {++S[$NF]} END { for(a in S) print ...

  6. 大数据处理-Trie树

    大数据处理--Trie树 1.1.什么是Trie树 Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被 ...

  7. git branch --set-upstream hmyq/master master

    git branch --set-upstream hmyq/master master

  8. bash脚本IFS=',' read的意思

    IFS is the Input Field Separator, which means the string read will be split based on the characters ...

  9. Wise 打包细节

    细节 说明 添加卸载快捷方式 缺省的安装程序快捷方式中没有卸载项:只能通过控制面板删除,或者主程序目录下的UnWise.exe来卸载.实际上,该文件就可以作为卸载程序. 可以复制一个快捷方式,将程序名 ...

  10. 探讨instanceof实现原理,并用两种方法模拟实现 instanceof

    在开始之前先了解下js数据类型 js基本数据类型: null undefined number boolean string js引用数据类型: function object array 一说ins ...