基于shiro进阶

更改了数据库表

之前的PageController是通过@RequiresPermissions和@RequiresRoles进行是否有权限/是否有角色的判定调用@RequestMapping路径

在PermissionService中加入了两个方法:needInterceptor, listPermissionURLs

needInterceptor表示是否要进行拦截,判断依据是如果访问的某个url,在权限系统里存在,就要进行拦截.

如果不存在就放行了. 这一种策略,也可以切换成另一个,即:

访问的地址如果不存在于权限系统中,就提示没有拦截.这两种做法没有对错之分,取决于业务上希望如何制定权限策略。

listPermissionURLs(User user)用来获取某个用户所拥有的权限地址集合

package com.how2java.service.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import com.how2java.mapper.PermissionMapper;
import com.how2java.mapper.RolePermissionMapper;
import com.how2java.pojo.Permission;
import com.how2java.pojo.PermissionExample;
import com.how2java.pojo.Role;
import com.how2java.pojo.RolePermission;
import com.how2java.pojo.RolePermissionExample;
import com.how2java.service.PermissionService;
import com.how2java.service.RoleService;
import com.how2java.service.UserService; @Service
public class PermissionServiceImpl implements PermissionService { @Autowired
PermissionMapper permissionMapper;
@Autowired
UserService userService;
@Autowired
RoleService roleService;
@Autowired
RolePermissionMapper rolePermissionMapper; @Override
public Set<String> listPermissions(String userName) {
Set<String> result = new HashSet<>();
List<Role> roles = roleService.listRoles(userName); List<RolePermission> rolePermissions = new ArrayList<>(); for (Role role : roles) {
RolePermissionExample example = new RolePermissionExample();
example.createCriteria().andRidEqualTo(role.getId());
List<RolePermission> rps = rolePermissionMapper.selectByExample(example);
rolePermissions.addAll(rps);
} for (RolePermission rolePermission : rolePermissions) {
Permission p = permissionMapper.selectByPrimaryKey(rolePermission.getPid());
result.add(p.getName());
} return result;
} @Override
public void add(Permission u) {
permissionMapper.insert(u);
} @Override
public void delete(Long id) {
permissionMapper.deleteByPrimaryKey(id);
} @Override
public void update(Permission u) {
permissionMapper.updateByPrimaryKeySelective(u);
} @Override
public Permission get(Long id) {
return permissionMapper.selectByPrimaryKey(id);
} @Override
public List<Permission> list() {
PermissionExample example = new PermissionExample();
example.setOrderByClause("id desc");
return permissionMapper.selectByExample(example); } @Override
public List<Permission> list(Role role) {
List<Permission> result = new ArrayList<>();
RolePermissionExample example = new RolePermissionExample();
example.createCriteria().andRidEqualTo(role.getId());
List<RolePermission> rps = rolePermissionMapper.selectByExample(example);
for (RolePermission rolePermission : rps) {
result.add(permissionMapper.selectByPrimaryKey(rolePermission.getPid()));
} return result;
} @Override
public boolean needInterceptor(String requestURI) {
List<Permission> ps = list();
for (Permission p : ps) {
if (p.getUrl().equals(requestURI))
return true;
}
return false;
} @Override
public Set<String> listPermissionURLs(String userName) {
Set<String> result = new HashSet<>();
List<Role> roles = roleService.listRoles(userName); List<RolePermission> rolePermissions = new ArrayList<>(); for (Role role : roles) {
RolePermissionExample example = new RolePermissionExample();
example.createCriteria().andRidEqualTo(role.getId());
List<RolePermission> rps = rolePermissionMapper.selectByExample(example);
rolePermissions.addAll(rps);
} for (RolePermission rolePermission : rolePermissions) {
Permission p = permissionMapper.selectByPrimaryKey(rolePermission.getPid());
result.add(p.getUrl());
} return result;
} }

注意其中的for循环,是否可以进行更优化的写法

URLPathMatchingFilter, PathMatchingFilter是shiro内置过滤器.URL...继承了Path...

基本思路:

1. 如果没登录就跳转到登录

2. 如果当前访问路径没有在权限系统里维护,则允许访问

3. 当前用户所拥有的权限如何不包含当前的访问地址,则跳转到/unauthorized, 否则就允许访问

package com.how2java.filter;

import java.util.Set;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.PathMatchingFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired; import com.how2java.service.PermissionService; public class URLPathMatchingFilter extends PathMatchingFilter {
@Autowired
PermissionService permissionService; @Override
protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue)
throws Exception {
String requestURI = getPathWithinApplication(request); System.out.println("requestURI:" + requestURI); Subject subject = SecurityUtils.getSubject();
// 如果没有登录,就跳转到登录页面
if (!subject.isAuthenticated()) {
WebUtils.issueRedirect(request, response, "/login");
return false;
} // 看看这个路径权限里有没有维护,如果没有维护,一律放行(也可以改为一律不放行)
boolean needInterceptor = permissionService.needInterceptor(requestURI);
if (!needInterceptor) {
return true;
} else {
boolean hasPermission = false;
String userName = subject.getPrincipal().toString();
Set<String> permissionUrls = permissionService.listPermissionURLs(userName);
for (String url : permissionUrls) {
// 这就表示当前用户有这个权限
if (url.equals(requestURI)) {
hasPermission = true;
break;
}
} if (hasPermission)
return true;
else {
UnauthorizedException ex = new UnauthorizedException("当前用户没有访问路径 " + requestURI + " 的权限"); subject.getSession().setAttribute("ex", ex); WebUtils.issueRedirect(request, response, "/unauthorized");
return false;
} } }
}

以及applicationContext-shiro.xml做了改动

将urlPathMatchingFilter加入shiro使用这个过滤器

这样一样就配置全部的url路径了,而对应的角色没有和url对应起来.

为什么不把角色也对应起来,从代码开发角色来说是可以的,无非是role表添加一个url字段,但是从权限管理本身,当一个url即对应权限表的数据,又对应角色表的数据,

反而容易产生混淆.

这种呢,url地址,仅仅和权限表关联,从逻辑上明晰简单,更易维护.

requestURI:/
requestURI:/listProduct
requestURI:/deleteProduct
requestURI:/deleteOrder
requestURI:/deleteOrder
requestURI:/deleteOrder
requestURI:/unauthorized
requestURI:/deleteProduct
requestURI:/listProduct

查看日志也会较为轻松

[Shiro] - 基于URL配置动态权限的更多相关文章

  1. Apache Shiro(六)-基于URL配置权限

    数据库 先准备数据库啦. DROP DATABASE IF EXISTS shiro; CREATE DATABASE shiro DEFAULT CHARACTER SET utf8; USE sh ...

  2. 如何兼容所有Android版本选择照片或拍照然后裁剪图片--基于FileProvider和动态权限的实现

    我们知道, Android操作系统一直在进化. 虽然说系统是越来越安全, 可靠, 但是对于开发者而言, 开发难度是越来越大的, 需要注意的兼容性问题, 也越来越多. 就比如在Android平台上拍照或 ...

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

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

  4. 基于url的权限管理

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

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

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

  6. 基于URL权限拦截的实现

    一.实现原理 1.实现原理   本示例采用SpringMVC的拦截器来实现一个基于URL的权限拦截. 2.权限管理流程 二.数据库搭建 1.用户表(sys_user) (1)表结构 (2)表字段说明 ...

  7. SpringBoot整合SpringSecurityOauth2实现鉴权-动态权限

    写在前面 思考:为什么需要鉴权呢? 系统开发好上线后,API接口会暴露在互联网上会存在一定的安全风险,例如:爬虫.恶意访问等.因此,我们需要对非开放API接口进行用户鉴权,鉴权通过之后再允许调用. 准 ...

  8. SpringBoot整合mybatis、shiro、redis实现基于数据库的细粒度动态权限管理系统实例

    1.前言 本文主要介绍使用SpringBoot与shiro实现基于数据库的细粒度动态权限管理系统实例. 使用技术:SpringBoot.mybatis.shiro.thymeleaf.pagehelp ...

  9. 项目一:第十二天 1、常见权限控制方式 2、基于shiro提供url拦截方式验证权限 3、在realm中授权 5、总结验证权限方式(四种) 6、用户注销7、基于treegrid实现菜单展示

    1 课程计划 1. 常见权限控制方式 2. 基于shiro提供url拦截方式验证权限 3. 在realm中授权 4. 基于shiro提供注解方式验证权限 5. 总结验证权限方式(四种) 6. 用户注销 ...

随机推荐

  1. WebDriver 常用操作

    1 浏览器操作 2 窗口和弹框操作 3 cookies 操作 4 简单对象的定位 5 页面元素操作 6 鼠标事件 7 键盘事件 1 浏览器操作 #属性: driver.current_url #用于获 ...

  2. awesome go library 库,推荐使用的golang库

    https://github.com/avelino/awesome-go https://github.com/spf13/cobra                        # A Comm ...

  3. Kylin安装部署

    一.安装准备 1.操作系统 Centos 7.x 2.时间问题 集群内所有节点时间一定要同步. NTP.Chrony 3.用户 创建hadoop组和hadoop用户,并做ssh免密码登录 4.Hado ...

  4. Biorhythms(中国剩余定理)

    http://shuxueshi.jie.blog.163.com/blog/static/13611628820104179856631/ 这篇博客写的很棒! #include<stdio.h ...

  5. [LeetCode] 680. Valid Palindrome II_Easy tag: Two Pointers

    Given a non-empty string s, you may delete at most one character. Judge whether you can make it a pa ...

  6. 修改class文件

    http://yucaifu1989.iteye.com/blog/1850500 http://blog.csdn.net/hexin373/article/details/6669813 使用ja ...

  7. EF6添加mysql的edmx实体时报错:无法生成模型:“System.Data.StrongTypingException: 表“TableDetails”中列“IsPrimaryKey”的值为 DBNull

    EF6.1.3 ,使用mysql5.7的实体数据模型时,提示: 由于出现以下异常,无法生成模型:“System.Data.StrongTypingException: 表“TableDetails”中 ...

  8. linux字符处理命令 sort(部分转载)

    [root@LocalWeb01 ~]# sort /etc/passwd |less   (升序 ) [root@LocalWeb01 ~]# sort -r /etc/passwd |less ( ...

  9. 护眼:我的DIY电脑护眼妙招

    每天对着电脑,埋头敲代码,一段时间之后.总是觉得眼睛很涩很难受,所以找到一些对抗的视疲劳的方法.不用花费任何钱,可以让眼睛享受地看着我们的屏幕,方法很简单,过来看看(小伎俩,大牛勿笑~) 一.WIN7 ...

  10. MongoDB ----基于分布式文件存储的数据库

    参考: http://www.cnblogs.com/huangxincheng/category/355399.html http://www.cnblogs.com/daizhj/category ...