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. java使用BigDecimal 实现随机金额红包拆分算法

    原创代码,引用注明出处:https://www.cnblogs.com/guangxiang/p/12218714.html @Servicepublic class SplitRedPacketsS ...

  2. Tmux和一点nohup

    1.当我们用ssh连接服务器时,只有一个终端,但有时候我们希望有多个. 2.有些程序需要运行一些时间,在这个时间里,我们希望可以去做其他的事情. 3.有的程序要跑好几个小时,这时候,我们希望断开远程连 ...

  3. Javascript声明和使用变量

    1.1变量的声明 要在程序中使用变量,就必须从声明变量学起,因为Javascript语法与我们基础的其他程序语言声明变量的方法略有不同,但是Javascript语法的变量应用非常强大,使用也非常简单. ...

  4. Mysql插入数据里有中文字符出现Incorrect string value的错误

    问题:Mysql插入数据里有中文字符出现Incorrect string value的错误   描述:CMD里直接敲代码插入数据   提示的部分截取为:ERROR 1366 (HY000): Inco ...

  5. ES6 之 第七种数据类型Symbol

    概述 为了减少对象的属性名冲突,ES6引入新的原始数据类型Symbol,JS的第七种数据类型. Symbol 能够保证每个属性的名字都是独一无二,这样就能从根本上防止属性名冲突. Symbol 值能够 ...

  6. winform屏蔽鼠标右键

    /// <summary> /// 屏蔽右键 /// </summary> internal class MenuHandler : IContextMenuHandler { ...

  7. Django1.11序列化与反序列化

    django序列化与反序列化 from rest_framwork import serializers serializers.ModelSerializer 模型类序列化器,必须依据模型类创建序列 ...

  8. STM32F407的Modbus做为主站与从站通讯

    在调试STM32F407的串口Modbus通讯之前,也使用过Modbus通讯,只不过都是在PLC或则昆仑通态的触摸屏上使用直接调用现成的库里面的模块,驱动就可以,相对于STM32来,使用PLC库里面的 ...

  9. 用Chrome网页获取PDF?

    在网页浏览的时候,我常常想保存网页上的内容 这时候有几种选择,要么copy and paste,要么windows自带截图,要么就是借用tencent的截图工具... 但是对于一些用chrome预览的 ...

  10. 启动zookeeper却没有进程

    第一次: 没有jdk,安装好jdk就可以了 第二次: java的环境变量没配好,按照下图的配就行: Java_HOME和jre_HOME都是jdk的目录就行 最后两行不加试试,好像都没多大关系 应该是 ...