shiro PermissionUtil

Posted tonggc1668

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shiro PermissionUtil相关的知识,希望对你有一定的参考价值。

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的主要内容,如果未能解决你的问题,请参考以下文章

shiro教程- shiro介绍

Shiro-----Shiro认证

Shiro - Shiro简介;Shiro与Spring Security区别;Spring Boot集成Shiro

[shiro] - 怎样使用shiro?

每天学点Shiro-shiro标签

shiro学习笔记_0100_shiro简介