package org.linlinjava.litemall.admin.util;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.linlinjava.litemall.admin.annotation.RequiresPermissionsDesc; public class Permission {
private RequiresPermissions requiresPermissions;
private RequiresPermissionsDesc requiresPermissionsDesc;
private String api; public RequiresPermissions getRequiresPermissions() {
return requiresPermissions;
} public RequiresPermissionsDesc getRequiresPermissionsDesc() {
return requiresPermissionsDesc;
} public void setRequiresPermissions(RequiresPermissions requiresPermissions) {
this.requiresPermissions = requiresPermissions;
} public void setRequiresPermissionsDesc(RequiresPermissionsDesc requiresPermissionsDesc) {
this.requiresPermissionsDesc = requiresPermissionsDesc;
} public String getApi() {
return api;
} public void setApi(String api) {
this.api = api;
}
}
package org.linlinjava.litemall.admin.util;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.linlinjava.litemall.admin.annotation.RequiresPermissionsDesc;
import org.linlinjava.litemall.admin.vo.PermVo;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Controller;
import org.springframework.util.ClassUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import java.lang.reflect.Method;
import java.util.*; public class PermissionUtil { public static List<PermVo> listPermVo(List<Permission> permissions) {
List<PermVo> root = new ArrayList<>();
for (Permission permission : permissions) {
RequiresPermissions requiresPermissions = permission.getRequiresPermissions();
RequiresPermissionsDesc requiresPermissionsDesc = permission.getRequiresPermissionsDesc();
String api = permission.getApi(); String[] menus = requiresPermissionsDesc.menu();
if (menus.length != 2) {
throw new RuntimeException("目前只支持两级菜单");
}
String menu1 = menus[0];
PermVo perm1 = null;
for (PermVo permVo : root) {
if (permVo.getLabel().equals(menu1)) {
perm1 = permVo;
break;
}
}
if (perm1 == null) {
perm1 = new PermVo();
perm1.setId(menu1);
perm1.setLabel(menu1);
perm1.setChildren(new ArrayList<>());
root.add(perm1);
}
String menu2 = menus[1];
PermVo perm2 = null;
for (PermVo permVo : perm1.getChildren()) {
if (permVo.getLabel().equals(menu2)) {
perm2 = permVo;
break;
}
}
if (perm2 == null) {
perm2 = new PermVo();
perm2.setId(menu2);
perm2.setLabel(menu2);
perm2.setChildren(new ArrayList<>());
perm1.getChildren().add(perm2);
} String button = requiresPermissionsDesc.button();
PermVo leftPerm = null;
for (PermVo permVo : perm2.getChildren()) {
if (permVo.getLabel().equals(button)) {
leftPerm = permVo;
break;
}
}
if (leftPerm == null) {
leftPerm = new PermVo();
leftPerm.setId(requiresPermissions.value()[0]);
leftPerm.setLabel(requiresPermissionsDesc.button());
leftPerm.setApi(api);
perm2.getChildren().add(leftPerm);
} else {
// TODO
// 目前限制Controller里面每个方法的RequiresPermissionsDesc注解是唯一的
// 如果允许相同,可能会造成内部权限不一致。
throw new RuntimeException("权限已经存在,不能添加新权限");
} }
return root;
} public static List<Permission> listPermission(ApplicationContext context, String basicPackage) {
Map<String, Object> map = context.getBeansWithAnnotation(Controller.class);
List<Permission> permissions = new ArrayList<>();
for (Map.Entry<String, Object> entry : map.entrySet()) {
Object bean = entry.getValue();
if (!StringUtils.contains(ClassUtils.getPackageName(bean.getClass()), basicPackage)) {
continue;
} Class<?> clz = bean.getClass();
Class controllerClz = clz.getSuperclass();
RequestMapping clazzRequestMapping = AnnotationUtils.findAnnotation(controllerClz, RequestMapping.class);
List<Method> methods = MethodUtils.getMethodsListWithAnnotation(controllerClz, RequiresPermissions.class);
for (Method method : methods) {
RequiresPermissions requiresPermissions = AnnotationUtils.getAnnotation(method,
RequiresPermissions.class);
RequiresPermissionsDesc requiresPermissionsDesc = AnnotationUtils.getAnnotation(method,
RequiresPermissionsDesc.class); if (requiresPermissions == null || requiresPermissionsDesc == null) {
continue;
} String api = "";
if (clazzRequestMapping != null) {
api = clazzRequestMapping.value()[0];
} PostMapping postMapping = AnnotationUtils.getAnnotation(method, PostMapping.class);
if (postMapping != null) {
api = "POST " + api + postMapping.value()[0]; Permission permission = new Permission();
permission.setRequiresPermissions(requiresPermissions);
permission.setRequiresPermissionsDesc(requiresPermissionsDesc);
permission.setApi(api);
permissions.add(permission);
continue;
}
GetMapping getMapping = AnnotationUtils.getAnnotation(method, GetMapping.class);
if (getMapping != null) {
api = "GET " + api + getMapping.value()[0];
Permission permission = new Permission();
permission.setRequiresPermissions(requiresPermissions);
permission.setRequiresPermissionsDesc(requiresPermissionsDesc);
permission.setApi(api);
permissions.add(permission);
continue;
}
// TODO
// 这里只支持GetMapping注解或者PostMapping注解,应该进一步提供灵活性
throw new RuntimeException("目前权限管理应该在method的前面使用GetMapping注解或者PostMapping注解");
}
}
return permissions;
} public static Set<String> listPermissionString(List<Permission> permissions) {
Set<String> permissionsString = new HashSet<>();
for (Permission permission : permissions) {
permissionsString.add(permission.getRequiresPermissions().value()[0]);
}
return permissionsString;
}
}
package org.linlinjava.litemall.admin.vo;

import java.util.List;

public class PermVo {
private String id;
private String label;
private String api;
private List<PermVo> children; public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getLabel() {
return label;
} public void setLabel(String label) {
this.label = label;
} public void setApi(String api) {
this.api = api;
} public String getApi() {
return api;
} public List<PermVo> getChildren() {
return children;
} public void setChildren(List<PermVo> children) {
this.children = children;
} }
package org.linlinjava.litemall.admin.web;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.linlinjava.litemall.admin.annotation.RequiresPermissionsDesc;
import org.linlinjava.litemall.admin.service.LogHelper;
import org.linlinjava.litemall.core.util.RegexUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.core.util.bcrypt.BCryptPasswordEncoder;
import org.linlinjava.litemall.core.validator.Order;
import org.linlinjava.litemall.core.validator.Sort;
import org.linlinjava.litemall.db.domain.LitemallAdmin;
import org.linlinjava.litemall.db.service.LitemallAdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import javax.validation.constraints.NotNull;
import java.util.List; import static org.linlinjava.litemall.admin.util.AdminResponseCode.*; @RestController
@RequestMapping("/admin/admin")
@Validated
public class AdminAdminController {
private final Log logger = LogFactory.getLog(AdminAdminController.class); @Autowired
private LitemallAdminService adminService;
@Autowired
private LogHelper logHelper; @RequiresPermissions("admin:admin:list")
@RequiresPermissionsDesc(menu = {"系统管理", "管理员管理"}, button = "查询")
@GetMapping("/list")
public Object list(String username,
@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer limit,
@Sort @RequestParam(defaultValue = "add_time") String sort,
@Order @RequestParam(defaultValue = "desc") String order) {
List<LitemallAdmin> adminList = adminService.querySelective(username, page, limit, sort, order);
return ResponseUtil.okList(adminList);
} private Object validate(LitemallAdmin admin) {
String name = admin.getUsername();
if (StringUtils.isEmpty(name)) {
return ResponseUtil.badArgument();
}
if (!RegexUtil.isUsername(name)) {
return ResponseUtil.fail(ADMIN_INVALID_NAME, "管理员名称不符合规定");
}
String password = admin.getPassword();
if (StringUtils.isEmpty(password) || password.length() < 6) {
return ResponseUtil.fail(ADMIN_INVALID_PASSWORD, "管理员密码长度不能小于6");
}
return null;
} @RequiresPermissions("admin:admin:create")
@RequiresPermissionsDesc(menu = {"系统管理", "管理员管理"}, button = "添加")
@PostMapping("/create")
public Object create(@RequestBody LitemallAdmin admin) {
Object error = validate(admin);
if (error != null) {
return error;
} String username = admin.getUsername();
List<LitemallAdmin> adminList = adminService.findAdmin(username);
if (adminList.size() > 0) {
return ResponseUtil.fail(ADMIN_NAME_EXIST, "管理员已经存在");
} String rawPassword = admin.getPassword();
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
String encodedPassword = encoder.encode(rawPassword);
admin.setPassword(encodedPassword);
adminService.add(admin);
logHelper.logAuthSucceed("添加管理员", username);
return ResponseUtil.ok(admin);
} @RequiresPermissions("admin:admin:read")
@RequiresPermissionsDesc(menu = {"系统管理", "管理员管理"}, button = "详情")
@GetMapping("/read")
public Object read(@NotNull Integer id) {
LitemallAdmin admin = adminService.findById(id);
return ResponseUtil.ok(admin);
} @RequiresPermissions("admin:admin:update")
@RequiresPermissionsDesc(menu = {"系统管理", "管理员管理"}, button = "编辑")
@PostMapping("/update")
public Object update(@RequestBody LitemallAdmin admin) {
Object error = validate(admin);
if (error != null) {
return error;
} Integer anotherAdminId = admin.getId();
if (anotherAdminId == null) {
return ResponseUtil.badArgument();
} // 不允许管理员通过编辑接口修改密码
admin.setPassword(null); if (adminService.updateById(admin) == 0) {
return ResponseUtil.updatedDataFailed();
} logHelper.logAuthSucceed("编辑管理员", admin.getUsername());
return ResponseUtil.ok(admin);
} @RequiresPermissions("admin:admin:delete")
@RequiresPermissionsDesc(menu = {"系统管理", "管理员管理"}, button = "删除")
@PostMapping("/delete")
public Object delete(@RequestBody LitemallAdmin admin) {
Integer anotherAdminId = admin.getId();
if (anotherAdminId == null) {
return ResponseUtil.badArgument();
} // 管理员不能删除自身账号
Subject currentUser = SecurityUtils.getSubject();
LitemallAdmin currentAdmin = (LitemallAdmin) currentUser.getPrincipal();
if (currentAdmin.getId().equals(anotherAdminId)) {
return ResponseUtil.fail(ADMIN_DELETE_NOT_ALLOWED, "管理员不能删除自己账号");
} adminService.deleteById(anotherAdminId);
logHelper.logAuthSucceed("删除管理员", admin.getUsername());
return ResponseUtil.ok();
}
}
package org.linlinjava.litemall.admin.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresPermissionsDesc {
String[] menu(); String button();
}

shiro PermissionUtil的更多相关文章

  1. shiro权限管理框架与springmvc整合

    shiro是apache下的一个项目,和spring security类似,用于用户权限的管理‘ 但从易用性和学习成本上考虑,shiro更具优势,同时shiro支持和很多接口集成 用户及权限管理是众多 ...

  2. springmvc 多数据源 SSM java redis shiro ehcache 头像裁剪

    获取下载地址   QQ 313596790  A 调用摄像头拍照,自定义裁剪编辑头像 B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,开发利器)+快速构建表单;  技术:31359679 ...

  3. java springMVC SSM 操作日志 4级别联动 文件管理 头像编辑 shiro redis

    A 调用摄像头拍照,自定义裁剪编辑头像 B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,开发利器)+快速构建表单;  技术:313596790freemaker模版技术 ,0个代码不用写 ...

  4. springmvc SSM shiro redis 后台框架 多数据源 代码生成器

    A集成代码生成器 [正反双向(单表.主表.明细表.树形表,开发利器)+快速构建表单 下载地址    ; freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本,处理类 ...

  5. springmvc SSM 多数据源 shiro redis 后台框架 整合

    A集成代码生成器 [正反双向(单表.主表.明细表.树形表,开发利器)+快速构建表单 下载地址    ; freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本,处理类 ...

  6. SpringMVC+Shiro权限管理【转】

    1.权限的简单描述 2.实例表结构及内容及POJO 3.Shiro-pom.xml 4.Shiro-web.xml 5.Shiro-MyShiro-权限认证,登录认证层 6.Shiro-applica ...

  7. shiro的使用2 灵活使用shiro的密码服务模块

    shiro最闪亮的四大特征是认证,授权,加密,会话管理. 上一篇已经演示了如何使用shiro的授权模块,有了shiro这个利器,可以以统一的编码方式对用户的登入,登出,认证进行管理,相当的优雅. 为了 ...

  8. shiro的使用1 简单的认证

    最近在重构,有空学了一个简单的安全框架shiro,资料比较少,在百度和google上能搜到的中文我看过了,剩下的时间有空会研究下官网的文章和查看下源码, 简单的分享一些学习过程: 1,简单的一些概念上 ...

  9. shiro实现session共享

    session共享:在多应用系统中,如果使用了负载均衡,用户的请求会被分发到不同的应用中,A应用中的session数据在B应用中是获取不到的,就会带来共享的问题. 假设:用户第一次访问,连接的A服务器 ...

随机推荐

  1. shell 疑难

    #!/bin/bashBIN=`which $0`BIN=`dirname ${BIN}`BIN=`cd "$BIN"; pwd`  #列出脚本所在目录全局路径

  2. const成员函数返回*this

    #include <iostream> using namespace std; class A{ public: A &set(char); const A &displ ...

  3. DLL对应的导入库一定会生成的

    测试代码: #pragma once #define TESTDEPEND_EXPORTS #ifdef TESTDEPEND_EXPORTS #define TESTDEPEND_API __dec ...

  4. 前端 Docker 镜像体积优化

    如果 2019 年技术圈有十大流行词,容器化肯定占有一席之地,随着 Docker 的风靡,前端领域应用到 Docker 的场景也越来越多,本文主要来讲述下开源的分布式图数据库 Nebula Graph ...

  5. 1)warning LNK4233

    名称 test.exe 包含非 ASCII 字符,在具有除 936 以外的 ANSI 代码页的系统上可能不能加载 DLL 名称 练习动态库.dll 包含非 ASCII 字符,如果系统没有与用于链接此 ...

  6. 吴裕雄--天生自然 JAVASCRIPT开发学习:HTML DOM 节点列表

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  7. C++ spdlog日志管理

    [1]spdlog简介 spdlog是一个开源的.快速的.仅有头文件的基于C++11实现的一款C++专用日志管理库. [2]源码下载 下载地址:https://github.com/gabime/sp ...

  8. slam库安装

    Ceres安装: 1.Ceres是一个cmak工程,首先要安装他的依赖项,使用apt-get安装. sudo apt-get install liblapack-dev libsuitesparse- ...

  9. 89.QuerySet API常用方法使用详解:count,first,last,aggregate,exists

    1.count():计算数据的个数. 计算数据的个数可以使用count,在python中使用len()也可以计算数据的个数,但是相对来说效率没有使用count()效率高,因为在底层是使用select ...

  10. Spring Cloud Alibaba 教程 | Nacos(一)

    什么是Nacos Nacos是一个更易于构建云原生应用的动态服务发现.配置管理和服务管理平台. Nacos 致力于帮助您发现.配置和管理微服务.Nacos提供了一组简单易用的特性集,帮助您快速实现动态 ...