# 接口权限

接口权限负责配置不同角色调用接口的权限。

  • 在实际开发项目中有些敏感接口,只能有固定的一些角色才能调用,普通角色是不能调用的。
  • 接口权限是针对于菜单页面的配置,而授权则基于角色。完整实现过程为:在需要做接口权限的菜单页面上配置接口权限场景,并完成角色授权。 如果菜单页面存在接口权限且角色未授权接口权限,则默认角色无访问菜单接口的权限

# 接口权限使用

# 1.概述

接口权限主要分为全局拦截器注解+aop两种方式。注意:注解方式优先级高于拦截器方式。

# 2.接口权限使用

# 2.1.相关注解/接口

  • 全局拦截器:无需特殊处理,在接口权限配置中维护接口信息并完成角色授权以后立即生效。拦截器部分代码如下:

/**
 * @program: hos-app
 * @author: whh
 * @create: 2022-08-13 09:54
 */
public class PermAuthInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
        if(handler instanceof HandlerMethod) {
            String methodName = ((HandlerMethod) handler).getMethod().getName();//获取方法名
            String className = ((HandlerMethod) handler).getBeanType().getName();//获取类全路径
            BaseUser user = SecurityUtils.getLoginUser();
            //还没有登录直接放行
            if(CommonUtils.isNull(user)){
                return true;
            }
            //如果是开发者账号则放行
            if (SecurityUtils.isAdmin()) {
                return true;
            }
            PreAuth classPreAuth = ((HandlerMethod) handler).getBeanType().getAnnotation(PreAuth.class);
            //如果存在权限注解放行
            if (CommonUtils.isNotNull(classPreAuth)) {
                //将路径的方法名和类名放入缓存
                CacheTenantUtil.put(CacheConstant.PRE_CACHE_CODE,className+","+methodName,request.getRequestURI(),String.class);
                return true;
            }
            //..........
       }

}

  • 注解+aop:此方式是通过在接口类或者方法上填写注解@PreAuth,在aop中通过注解的spel表达式调用接口IPermissionHandler的实现类完成接口权限认证。

IPermissionHandler接口类主要包含两个方法permissionAll()hasPermission()

  1. permissionAll()方法:角色中只要存在任何一个当前类或者方法的编码,就允许通过校验

  2. hasPermission()方法:判断账号所拥有的角色是否包含设置的权限编码,permission为前端维护的编码。

接口代码示例: 具体实现类ApiPermissionHandler,部分实现代码如下:

//------------ApiPermissionHandler------------------
/**
 * 权限校验通用接口
 *
 * @author Chill
 */
public class ApiPermissionHandler implements IPermissionHandler {

	/**
	 * 角色中只要存在任何一个当前类或者方法的编码,就允许通过校验
	 *
	 * @return {boolean}
	 */
	@Override
	public boolean permissionAll() {
    		HttpServletRequest request = BaseHttpContextUtils.getRequest();
    		//如果是开发者账户,默认拥有所有的权限
    		if (SecurityUtils.isAdmin()){
    			return true;
    		}
    		BaseUser user = SecurityUtils.getLoginUser();
    		if (request == null || user == null) {
    			return false;
    		}
    		String cmName=CacheTenantUtil.get(CacheConstant.PRE_CACHE_CODE,request.getRequestURI(),String.class);//从缓存中获取名称
    		String methodName = cmName.split(",")[1];
    		String className =cmName.split(",")[0];
    		return PreAuthUtil.isPrePass(className, methodName);
    	}

	/**
	 * 判断账号所拥有的角色是否包含设置的权限编码,permission为前端维护的编码
	 *
	 * @param permission 权限编号
	 * @return {boolean}
	 */
	@Override
    public boolean hasPermission(String permission) {
	    //如果是开发者账户,默认拥有所有的权限
    	if (SecurityUtils.isAdmin()){
    	    return true;
    	}
    	HttpServletRequest request = BaseHttpContextUtils.getRequest();
    	BaseUser user = SecurityUtils.getLoginUser();
    	if (request == null || user == null) {
    	    return false;
    	}
    	String postId = user.getPostId();
    	List<Role> roles = hosPostRoleService.getActivedRoleMsgByPostId(postId);
    	String roleIds = RoleUtil.getRoleId(roles);
    	return validatorPermissionCode(permission, roleIds);
	}
}

# 2.2.接口权限使用

使用 全局拦截器方式配置时无需做任何配置,在使用注解+aop的方式时,只需在对应的接口类型或者方法上添加@PreAuth注解即可:

@RestController
@RequestMapping("${sys.backendPath}/sys/resources")
@Api(tags = "资源管理")
@PreAuth("permissionAll()") //写在类上对整个类起作用
public class ResourceController {

    @Autowired
    private ResourceService resourceService;

    @GetMapping("/list")
    @ApiOperation(value = "查询资源列表")
    public BaseResponse<ResourceTableVO> list(ResourceDTO resourceDTO) {
        return BaseResponse.success(new ResourceTableVO(resourceService.listResources(resourceDTO)));
    }

    @ApiOperation("新增资源")
    @PostMapping("/insert")
    @PreAuth("hasPermission('base-resource-insert')")//写在方法上此方法起作用
    @OperLog(title = "资源管理", content = "新增资源")
    public BaseResponse<Integer> insert(@Validated @RequestBody Resource resource) {
        return BaseResponse.success(this.resourceService.insert(resource));
    }


提示

如果类与方法上同时存在注解时,方法上的注解配置不生效。

# 接口权限配置

# 1. 概述

接口权限管理模块负责对菜单维护接口权限配置。主要功能包含查询新增修改删除查看导入导出数据日志数据生命周期

【菜单路径:】系统管理–>接口权限

接口权限路径

# 2.查询接口权限

在接口权限页面可以通过 菜单名称编码 字段筛选接口权限,如下图所示:

查询接口权限列表

# 3.新增接口权限

在接口权限列表页面,点击表格上方的【新增】按钮,跳转新增接口权限页面,如下图所示:

新增接口权限

  • 接口权限参数信息说明
属性名        属性说明
编码 当前接口权限内容的唯一标识,用于后端接口授权使用,必填
名称 当前接口权限内容的名称,必填
类路径 当前接口权限所对应的后端实体的详细类路径,必填
方法 权限生效的方法
备注 备注信息

提示

1.如果接口方法设置为*时,代表当前接口权限对所填实体类下的所有方法生效。
2.首页选择左侧菜单时,只有类型为菜单类型的节点才允许添加接口权限。

# 4.修改接口权限

通过点击表格行的【编辑】按钮跳转修改页,来对接口权限进行修改。如下图所示:

修改接口权限

接口权限信息详细配置参见新增接口权限

# 5.删除接口权限

勾选接口权限后,点击【删除】按钮,即可对接口权限进行批量删除。

删除接口权限

# 6.查看接口权限

点击表格行内的查看按钮,可以查看数据权限的明细内容。如下图所示:

查看字典

# 7.导入接口权限

接口权限提供表格的导入功能,点击导入下载模板,维护数据选择导入类型即可导入接口权限,详情参考导入流程

# 8.导出接口权限

接口权限提供表格的导出功能,点击导出按钮选择需要导出的字段,即可导出接口权限数据,详情参考导出流程

# 9.查看数据日志

接口权限提供数据日志的查询功能,点击数据日志按钮即可进入数据日志列表页面,详情参考数据日志

# 10.查看数据生命周期

接口权限提供生命周期的查看功能,勾选表格行选中框,点击生命周期即可查看该条数据的生命周期信息,详情参考生命周期