增加RequiresPermissions代理注解

This commit is contained in:
wuy 2019-06-14 23:21:54 +08:00
parent eb4cd5569f
commit 8689848fb1
6 changed files with 196 additions and 3 deletions

View File

@ -0,0 +1,25 @@
package com.diboot.shiro.bind.annotation;
import java.lang.annotation.*;
/**
* controller上注解用于标记权限的菜单分类
* @author : wee
* @version v2.0
* @Date 2019-06-14 23:00
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface PermissionsMenu {
/**
* 菜单编码
* @return
*/
String menuCode();
/**
* 菜单名称
* @return
*/
String menuName();
}

View File

@ -0,0 +1,47 @@
package com.diboot.shiro.bind.annotation;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import java.lang.annotation.*;
/**
* @author : wee
* @version v2.0
* @Date 2019-06-14 17:50
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@RequiresPermissions("default")
public @interface RequiresPermissionsProxy {
/**
* 代理 {@link RequiresPermissions#value()}
*/
String[] value();
/**
* 代理 {@link RequiresPermissions#logical()}
*/
Logical logical() default Logical.AND;
/**
* 菜单编码
* @return
*/
String menuCode();
/**
* 菜单名称
* @return
*/
String menuName();
/**
* 权限名称
* @return
*/
String permissionName();
}

View File

@ -0,0 +1,30 @@
package com.diboot.shiro.bind.aop;
import com.diboot.shiro.bind.annotation.RequiresPermissionsProxy;
import com.diboot.shiro.bind.handler.PermissionProxyAnnotationHandler;
import org.apache.shiro.aop.AnnotationResolver;
import org.apache.shiro.authz.aop.AuthorizingAnnotationMethodInterceptor;
/**
* {@link RequiresPermissionsProxy} 拦截器
* @author : wee
* @version : v2.0
* @Date 2019-06-14 22:19
*/
public class PermissionProxyAnnotationMethodInterceptor extends AuthorizingAnnotationMethodInterceptor {
/**
* Default no-argument constructor that ensures this interceptor looks for
* {@link org.apache.shiro.authz.annotation.RequiresPermissions RequiresPermissions} annotations in a method declaration.
*/
public PermissionProxyAnnotationMethodInterceptor() {
super( new PermissionProxyAnnotationHandler() );
}
/**
* @param resolver
* @since 1.1
*/
public PermissionProxyAnnotationMethodInterceptor(AnnotationResolver resolver) {
super( new PermissionProxyAnnotationHandler(), resolver);
}
}

View File

@ -0,0 +1,69 @@
package com.diboot.shiro.bind.handler;
import com.diboot.shiro.bind.annotation.RequiresPermissionsProxy;
import org.apache.shiro.aop.AnnotationResolver;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.authz.aop.AuthorizingAnnotationHandler;
import org.apache.shiro.authz.aop.AuthorizingAnnotationMethodInterceptor;
import org.apache.shiro.authz.aop.PermissionAnnotationHandler;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Map;
/**
* {@link RequiresPermissionsProxy} 助手类 参考{@link PermissionAnnotationHandler}实现
* @author : wee
* @version : v2.0
* @Date 2019-06-14 22:19
*/
public class PermissionProxyAnnotationHandler extends AuthorizingAnnotationHandler {
private final static String REQUIRES_PERMISSIONS_VALUE = "value";
private final static String REQUIRES_PERMISSIONS_LOGICAL = "logical";
private final static String JDK_MEMBER_VALUES = "memberValues";
/**
* 标记服务的注解
*/
public PermissionProxyAnnotationHandler() {
super(RequiresPermissionsProxy.class);
}
/**
* {@link RequiresPermissionsProxy} 代理的内容赋值给{@link RequiresPermissions}
*/
@Override
public void assertAuthorized(Annotation a) throws AuthorizationException {
if (!(a instanceof RequiresPermissionsProxy)) {
return;
}
RequiresPermissionsProxy rrAnnotation = (RequiresPermissionsProxy) a;
try {
//获取RequiresPermissionsProxy上的RequiresPermissions注解
RequiresPermissions requiresPermissions = rrAnnotation.annotationType().getAnnotation(RequiresPermissions.class);
InvocationHandler invocationHandler = Proxy.getInvocationHandler(requiresPermissions);
/* memberValues 为JDK中存储所有成员变量值的Map {@link AnnotationInvocationHandler#memberValues}*/
Field jdkValue = invocationHandler.getClass().getDeclaredField(JDK_MEMBER_VALUES);
jdkValue.setAccessible(true);
/*获取RequiresPermissions对应的代理属性值*/
Map<String, Object> memberValues = (Map<String, Object>) jdkValue.get(invocationHandler);
/*动态设置RequiresPermissions注解的内容*/
memberValues.put(REQUIRES_PERMISSIONS_VALUE, rrAnnotation.value());
memberValues.put(REQUIRES_PERMISSIONS_LOGICAL, rrAnnotation.logical());
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}

View File

@ -1,10 +1,15 @@
package com.diboot.shiro.config;
import com.diboot.shiro.bind.aop.PermissionProxyAnnotationMethodInterceptor;
import com.diboot.shiro.jwt.BaseJwtAuthenticationFilter;
import com.diboot.shiro.jwt.BaseJwtRealm;
import org.apache.shiro.aop.AnnotationResolver;
import org.apache.shiro.authz.aop.*;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.aop.SpringAnnotationResolver;
import org.apache.shiro.spring.security.interceptor.AopAllianceAnnotationsAuthorizingMethodInterceptor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.AnonymousFilter;
@ -17,7 +22,9 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import javax.servlet.Filter;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/***
@ -96,6 +103,18 @@ public class ShiroConfig {
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
AopAllianceAnnotationsAuthorizingMethodInterceptor advice = (AopAllianceAnnotationsAuthorizingMethodInterceptor)authorizationAttributeSourceAdvisor.getAdvice();
//重置拦截器添加新的PermissionProxyAnnotationMethodInterceptor
List<AuthorizingAnnotationMethodInterceptor> interceptors =new ArrayList<>(6);
AnnotationResolver resolver = new SpringAnnotationResolver();
interceptors.add(new PermissionProxyAnnotationMethodInterceptor(resolver));
interceptors.add(new RoleAnnotationMethodInterceptor(resolver));
interceptors.add(new PermissionAnnotationMethodInterceptor(resolver));
interceptors.add(new AuthenticatedAnnotationMethodInterceptor(resolver));
interceptors.add(new UserAnnotationMethodInterceptor(resolver));
interceptors.add(new GuestAnnotationMethodInterceptor(resolver));
advice.setMethodInterceptors(interceptors);
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
return authorizationAttributeSourceAdvisor;
}

View File

@ -4,10 +4,11 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.diboot.core.controller.BaseCrudRestController;
import com.diboot.core.service.BaseService;
import com.diboot.core.util.BeanUtils;
import com.diboot.core.util.V;
import com.diboot.core.vo.JsonResult;
import com.diboot.core.vo.Pagination;
import com.diboot.core.vo.Status;
import com.diboot.shiro.bind.annotation.PermissionsMenu;
import com.diboot.shiro.bind.annotation.RequiresPermissionsProxy;
import com.diboot.shiro.entity.Permission;
import com.diboot.shiro.service.PermissionService;
import com.diboot.shiro.vo.PermissionVO;
@ -28,6 +29,7 @@ import java.util.List;
* @version 2018/12/23
* Copyright © www.dibo.ltd
*/
@PermissionsMenu(menuName = "权限", menuCode = "permission")
@RestController
@RequestMapping("/permission")
public class PermissionController extends BaseCrudRestController {
@ -45,8 +47,9 @@ public class PermissionController extends BaseCrudRestController {
* @return
* @throws Exception
*/
@RequiresPermissions("permission:list")
@GetMapping("/list")
@RequiresPermissionsProxy(value = {"permission:list"}, menuCode = "permission",
menuName = "权限", permissionName = "列表")
public JsonResult getVOList(HttpServletRequest request) throws Exception{
QueryWrapper<Permission> queryWrapper = buildQuery(request);
// 构建分页
@ -80,8 +83,8 @@ public class PermissionController extends BaseCrudRestController {
* @return
* @throws Exception
*/
@RequiresPermissions("permission:get")
@GetMapping("/{id}")
@RequiresPermissionsProxy(value = {"permission:get"}, menuCode = "permission", menuName = "权限", permissionName = "查看")
public JsonResult getModel(@PathVariable("id")Long id, HttpServletRequest request, ModelMap modelMap)
throws Exception{
PermissionVO vo = permissionService.getViewObject(id, PermissionVO.class);