优化权限控制,增加测试用例

This commit is contained in:
zhou-hao
2017-11-28 19:05:37 +08:00
parent 89863b6508
commit 133fd1ab28
13 changed files with 444 additions and 151 deletions

View File

@@ -7,20 +7,26 @@ import org.hswebframework.web.authorization.annotation.Authorize;
import org.hswebframework.web.authorization.define.AuthorizingContext;
import org.hswebframework.web.authorization.basic.handler.AuthorizingHandler;
import org.hswebframework.web.authorization.define.AuthorizeDefinition;
import org.hswebframework.web.authorization.define.Phased;
import org.hswebframework.web.authorization.exception.UnAuthorizedException;
import org.hswebframework.web.boost.aop.context.MethodInterceptorHolder;
import org.hswebframework.web.boost.aop.context.MethodInterceptorContext;
import org.hswebframework.web.controller.message.ResponseMessage;
import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RestController;
import java.lang.reflect.Method;
import java.util.Map;
/**
* @author zhouhao
*/
public class AopAuthorizingController extends StaticMethodMatcherPointcutAdvisor {
private static final long serialVersionUID = 1154190623020670672L;
public AopAuthorizingController(AuthorizingHandler authorizingHandler, AopMethodAuthorizeDefinitionParser aopMethodAuthorizeDefinitionParser) {
super((MethodInterceptor) methodInvocation -> {
@@ -29,22 +35,36 @@ public class AopAuthorizingController extends StaticMethodMatcherPointcutAdvisor
MethodInterceptorContext paramContext = holder.createParamContext();
AuthorizeDefinition definition = aopMethodAuthorizeDefinitionParser.parse(paramContext);
Object result = true;
boolean isControl = false;
if (null != definition) {
Authentication authentication = Authentication.current().orElseThrow(UnAuthorizedException::new);
if (!definition.isEmpty()) {
AuthorizingContext context = new AuthorizingContext();
context.setAuthentication(authentication);
context.setDefinition(definition);
context.setParamContext(paramContext);
authorizingHandler.handle(context);
isControl = true;
if (definition.getPhased() == Phased.before) {
authorizingHandler.handle(context);
result = methodInvocation.proceed();
} else {
result = methodInvocation.proceed();
context.setParamContext(holder.createParamContext(result));
authorizingHandler.handle(context);
}
}
}
return methodInvocation.proceed();
if (!isControl) {
result = methodInvocation.proceed();
}
return result;
});
}
@Override
public boolean matches(Method method, Class<?> aClass) {
//对controller进行控制

View File

@@ -1,5 +1,6 @@
package org.hswebframework.web.authorization.basic.define;
import lombok.*;
import org.hswebframework.web.authorization.access.DataAccessController;
import org.hswebframework.web.authorization.annotation.Authorize;
import org.hswebframework.web.authorization.annotation.Logical;
@@ -7,6 +8,7 @@ import org.hswebframework.web.authorization.annotation.RequiresDataAccess;
import org.hswebframework.web.authorization.annotation.RequiresExpression;
import org.hswebframework.web.authorization.define.AuthorizeDefinition;
import org.hswebframework.web.authorization.define.DataAccessDefinition;
import org.hswebframework.web.authorization.define.Phased;
import org.hswebframework.web.authorization.define.Script;
import java.util.Arrays;
@@ -19,6 +21,10 @@ import java.util.Set;
* @author zhouhao
* @since 3.0
*/
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class DefaultBasicAuthorizeDefinition implements AuthorizeDefinition {
private boolean dataAccessControl;
@@ -38,97 +44,23 @@ public class DefaultBasicAuthorizeDefinition implements AuthorizeDefinition {
private DataAccessDefinition dataAccessDefinition;
private Phased phased = Phased.before;
@Override
public Phased getPhased() {
return phased;
}
@Override
public int getPriority() {
return Integer.MIN_VALUE;
}
@Override
public boolean isDataAccessControl() {
return dataAccessControl;
}
@Override
public Set<String> getPermissions() {
return new HashSet<>(permissions);
}
@Override
public Set<String> getActions() {
return new HashSet<>(actions);
}
@Override
public Set<String> getRoles() {
return new HashSet<>(roles);
}
@Override
public Set<String> getUser() {
return new HashSet<>(user);
}
@Override
public Script getScript() {
return script;
}
@Override
public String getMessage() {
return message;
}
@Override
public Logical getLogical() {
return logical;
}
@Override
public boolean isEmpty() {
return permissions.isEmpty() && roles.isEmpty() && user.isEmpty() && script == null && dataAccessDefinition == null;
}
@Override
public DataAccessDefinition getDataAccessDefinition() {
return dataAccessDefinition;
}
public void setDataAccessDefinition(DataAccessDefinition dataAccessDefinition) {
this.dataAccessDefinition = dataAccessDefinition;
}
public void setActions(Set<String> actions) {
this.actions = actions;
}
public void setDataAccessControl(boolean dataAccessControl) {
this.dataAccessControl = dataAccessControl;
}
public void setLogical(Logical logical) {
this.logical = logical;
}
public void setMessage(String message) {
this.message = message;
}
public void setPermissions(Set<String> permissions) {
this.permissions = permissions;
}
public void setRoles(Set<String> roles) {
this.roles = roles;
}
public void setScript(Script script) {
this.script = script;
}
public void setUser(Set<String> user) {
this.user = user;
}
public void put(Authorize authorize) {
if (null == authorize || authorize.ignore()) {
return;
@@ -141,6 +73,7 @@ public class DefaultBasicAuthorizeDefinition implements AuthorizeDefinition {
logical = authorize.logical();
}
message = authorize.message();
phased=authorize.phased();
}
public void put(RequiresExpression expression) {

View File

@@ -3,6 +3,7 @@ package org.hswebframework.web.authorization.basic.define;
import org.hswebframework.web.authorization.annotation.Logical;
import org.hswebframework.web.authorization.define.AuthorizeDefinition;
import org.hswebframework.web.authorization.define.DataAccessDefinition;
import org.hswebframework.web.authorization.define.Phased;
import org.hswebframework.web.authorization.define.Script;
import java.util.Set;
@@ -17,6 +18,11 @@ public class EmptyAuthorizeDefinition implements AuthorizeDefinition {
private EmptyAuthorizeDefinition() {
}
@Override
public Phased getPhased() {
throw new UnsupportedOperationException();
}
@Override
public int getPriority() {
throw new UnsupportedOperationException();

View File

@@ -52,7 +52,6 @@ public class DefaultAuthorizingHandler implements AuthorizingHandler {
//表达式权限控制
handleExpression(context.getAuthentication(), context.getDefinition(), context.getParamContext());
}
protected void handleDataAccess(AuthorizingContext context) {

View File

@@ -0,0 +1,5 @@
package org.hswebframework.web.authorization.basic.handler;
public interface MethodProceedCallback {
void call(Object result);
}

View File

@@ -30,11 +30,11 @@ public final class DefaultDataAccessController implements DataAccessController {
throw new UnsupportedOperationException();
}
this.parent = parent;
addHandler(new CustomDataAccessHandler());
addHandler(new OwnCreatedDataAccessHandler());
addHandler(new ScriptDataAccessHandler());
addHandler(new FieldFilterDataAccessHandler());
addHandler(new FieldScopeDataAccessHandler());
addHandler(new CustomDataAccessHandler()).
addHandler(new OwnCreatedDataAccessHandler()).
addHandler(new ScriptDataAccessHandler()).
addHandler(new FieldFilterDataAccessHandler()).
addHandler(new FieldScopeDataAccessHandler());
}
@Override
@@ -43,7 +43,6 @@ public final class DefaultDataAccessController implements DataAccessController {
parent.doAccess(access, context);
}
return handlers.stream()
// TODO: 17-3-28 可以换成access对应的handler以提高效率
.filter(handler -> handler.isSupport(access))
.allMatch(handler -> handler.handle(access, context));
}

View File

@@ -6,13 +6,19 @@ import org.hswebframework.web.authorization.access.DataAccessConfig;
import org.hswebframework.web.authorization.access.DataAccessHandler;
import org.hswebframework.web.authorization.access.FieldFilterDataAccessConfig;
import org.hswebframework.web.authorization.define.AuthorizingContext;
import org.hswebframework.web.authorization.define.Phased;
import org.hswebframework.web.commons.entity.Entity;
import org.hswebframework.web.commons.entity.param.QueryParamEntity;
import org.hswebframework.web.commons.model.Model;
import org.hswebframework.web.controller.message.ResponseMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
/**
* 数据权限字段过滤处理,目前仅支持deny. {@link DataAccessConfig.DefaultType#DENY_FIELDS}
@@ -33,6 +39,7 @@ public class FieldFilterDataAccessHandler implements DataAccessHandler {
switch (access.getAction()) {
case Permission.ACTION_QUERY:
case Permission.ACTION_GET:
return doQueryAccess(filterDataAccessConfig, context);
case Permission.ACTION_UPDATE:
return doUpdateAccess(filterDataAccessConfig, context);
@@ -53,7 +60,7 @@ public class FieldFilterDataAccessHandler implements DataAccessHandler {
*/
protected boolean doUpdateAccess(FieldFilterDataAccessConfig accesses, AuthorizingContext params) {
Object supportParam = params.getParamContext().getParams().values().stream()
.filter(param -> (param instanceof Entity) || (param instanceof Model)||(param instanceof Map))
.filter(param -> (param instanceof Entity) || (param instanceof Model) || (param instanceof Map))
.findAny()
.orElse(null);
if (null != supportParam) {
@@ -73,18 +80,40 @@ public class FieldFilterDataAccessHandler implements DataAccessHandler {
return true;
}
@SuppressWarnings("all")
protected boolean doQueryAccess(FieldFilterDataAccessConfig access, AuthorizingContext context) {
QueryParamEntity entity = context.getParamContext().getParams()
.values().stream()
.filter(QueryParamEntity.class::isInstance)
.map(QueryParamEntity.class::cast)
.findAny().orElse(null);
if (entity == null) {
logger.warn("try validate query access, but query entity is null or not instance of org.hswebframework.web.commons.entity.Entity");
return true;
if (context.getDefinition().getPhased() == Phased.before) {
QueryParamEntity entity = context.getParamContext().getParams()
.values().stream()
.filter(QueryParamEntity.class::isInstance)
.map(QueryParamEntity.class::cast)
.findAny().orElse(null);
if (entity == null) {
logger.warn("try validate query access, but query entity is null or not instance of org.hswebframework.web.commons.entity.Entity");
return true;
}
entity.excludes(access.getFields().toArray(new String[access.getFields().size()]));
} else {
Object result = InvokeResultUtils.convertRealResult(context.getParamContext().getInvokeResult());
if (result instanceof Collection) {
((Collection) result).forEach(o -> setObjectPropertyNull(o, access.getFields()));
} else {
setObjectPropertyNull(result, access.getFields());
}
}
entity.excludes(access.getFields().toArray(new String[access.getFields().size()]));
return true;
}
protected void setObjectPropertyNull(Object obj, Set<String> fields) {
if (null == obj) {
return;
}
for (String field : fields) {
try {
BeanUtilsBean.getInstance().getPropertyUtils().setProperty(obj, field, null);
} catch (Exception ignore) {
}
}
}
}

View File

@@ -9,14 +9,18 @@ import org.hswebframework.web.authorization.access.DataAccessConfig;
import org.hswebframework.web.authorization.access.DataAccessHandler;
import org.hswebframework.web.authorization.access.FieldScopeDataAccessConfig;
import org.hswebframework.web.authorization.define.AuthorizingContext;
import org.hswebframework.web.authorization.define.Phased;
import org.hswebframework.web.commons.entity.param.QueryParamEntity;
import org.hswebframework.web.controller.QueryController;
import org.hswebframework.web.service.QueryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* @author zhouhao
@@ -38,8 +42,8 @@ public class FieldScopeDataAccessHandler implements DataAccessHandler {
if (controller != null) {
switch (access.getAction()) {
case Permission.ACTION_QUERY:
return doQueryAccess(own, context);
case Permission.ACTION_GET:
return doQueryAccess(own, context);
case Permission.ACTION_DELETE:
case Permission.ACTION_UPDATE:
return doRWAccess(own, context, controller);
@@ -78,29 +82,58 @@ public class FieldScopeDataAccessHandler implements DataAccessHandler {
}
@SuppressWarnings("all")
protected boolean doQueryAccess(FieldScopeDataAccessConfig access, AuthorizingContext context) {
QueryParamEntity entity = context.getParamContext().getParams()
.values().stream()
.filter(QueryParamEntity.class::isInstance)
.map(QueryParamEntity.class::cast)
.findAny().orElse(null);
if (entity == null) {
logger.warn("try validate query access, but query entity is null or not instance of org.hswebframework.web.commons.entity.Entity");
return true;
if (context.getDefinition().getPhased() == Phased.before) {
QueryParamEntity entity = context.getParamContext().getParams()
.values().stream()
.filter(QueryParamEntity.class::isInstance)
.map(QueryParamEntity.class::cast)
.findAny().orElse(null);
if (entity == null) {
logger.warn("try validate query access, but query entity is null or not instance of org.hswebframework.web.commons.entity.Entity");
return true;
}
//重构查询条件
//如: 旧的条件为 where column =? or column = ?
//重构后为: where creatorId=? and (column = ? or column = ?)
List<Term> oldParam = entity.getTerms();
//清空旧的查询条件
entity.setTerms(new ArrayList<>());
//添加一个查询条件
entity.addTerm(createQueryTerm(access))
//客户端提交的参数 作为嵌套参数
.nest().setTerms(oldParam);
} else {
Object result = InvokeResultUtils.convertRealResult(context.getParamContext().getInvokeResult());
if (result == null) {
return true;
}
if (result instanceof Collection) {
return ((Collection) result).stream().allMatch(obj -> propertyInScope(obj, access.getField(), access.getScope()));
} else {
return propertyInScope(result, access.getField(), access.getScope());
}
}
//重构查询条件
//如: 旧的条件为 where column =? or column = ?
//重构后为: where creatorId=? and (column = ? or column = ?)
List<Term> oldParam = entity.getTerms();
//清空旧的查询条件
entity.setTerms(new ArrayList<>());
//添加一个查询条件
entity.addTerm(createQueryTerm(access))
//客户端提交的参数 作为嵌套参数
.nest().setTerms(oldParam);
return true;
}
protected boolean propertyInScope(Object obj, String property, Set<Object> scope) {
if (null == obj) {
return false;
}
try {
Object value = BeanUtilsBean.getInstance().getProperty(obj, property);
if (null != value) {
return scope.contains(value);
}
} catch (Exception ignore) {
logger.warn("can not get property {} from {},{}", property, obj, ignore.getMessage());
}
return true;
}
protected Term createQueryTerm(FieldScopeDataAccessConfig access) {
Term term = new Term();
term.setType(Term.Type.and);

View File

@@ -0,0 +1,16 @@
package org.hswebframework.web.authorization.basic.handler.access;
import org.hswebframework.web.controller.message.ResponseMessage;
import org.springframework.http.ResponseEntity;
public class InvokeResultUtils {
public static Object convertRealResult(Object result) {
if (result instanceof ResponseMessage) {
return ((ResponseMessage) result).getResult();
}
if (result instanceof ResponseEntity) {
return ((ResponseEntity) result).getBody();
}
return result;
}
}

View File

@@ -1,5 +1,7 @@
package org.hswebframework.web.authorization.basic.handler.access;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.hswebframework.ezorm.core.param.Term;
import org.hswebframework.utils.ClassUtils;
import org.hswebframework.web.authorization.Permission;
@@ -7,6 +9,7 @@ import org.hswebframework.web.authorization.access.DataAccessConfig;
import org.hswebframework.web.authorization.access.DataAccessHandler;
import org.hswebframework.web.authorization.access.OwnCreatedDataAccessConfig;
import org.hswebframework.web.authorization.define.AuthorizingContext;
import org.hswebframework.web.authorization.define.Phased;
import org.hswebframework.web.commons.entity.Entity;
import org.hswebframework.web.commons.entity.RecordCreationEntity;
import org.hswebframework.web.commons.entity.param.QueryParamEntity;
@@ -15,12 +18,14 @@ import org.hswebframework.web.service.QueryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* TODO 完成注释
*
* @author zhouhao
*/
public class OwnCreatedDataAccessHandler implements DataAccessHandler {
@@ -37,12 +42,13 @@ public class OwnCreatedDataAccessHandler implements DataAccessHandler {
Object controller = context.getParamContext().getTarget();
if (controller != null) {
switch (access.getAction()) {
case Permission.ACTION_GET:
case Permission.ACTION_QUERY:
return doQueryAccess(own, context);
case Permission.ACTION_GET:
case Permission.ACTION_DELETE:
case Permission.ACTION_UPDATE:
return doRWAccess(own, context,controller);
return doRWAccess(own, context, controller);
case Permission.ACTION_ADD:
//put creator_id to result
return putCreatorId(own, context);
@@ -91,32 +97,60 @@ public class OwnCreatedDataAccessHandler implements DataAccessHandler {
}
protected boolean doQueryAccess(OwnCreatedDataAccessConfig access, AuthorizingContext context) {
Entity entity = context.getParamContext().getParams()
.values().stream()
.filter(Entity.class::isInstance)
.map(Entity.class::cast)
.findAny().orElse(null);
if (entity == null) {
logger.warn("try validate query access, but query entity is null or not instance of org.hswebframework.web.commons.entity.Entity");
String userId = context.getAuthentication().getUser().getId();
if (context.getDefinition().getPhased() == Phased.before) {
Entity entity = context.getParamContext().getParams()
.values().stream()
.filter(Entity.class::isInstance)
.map(Entity.class::cast)
.findAny().orElse(null);
if (entity == null) {
logger.warn("try validate query access, but query entity is null or not instance of org.hswebframework.web.commons.entity.Entity");
return true;
}
if (entity instanceof QueryParamEntity) {
QueryParamEntity queryParamEntity = ((QueryParamEntity) entity);
//重构查询条件
//如: 旧的条件为 where name =? or name = ?
//重构后为: where creatorId=? and (name = ? or name = ?)
List<Term> oldParam = queryParamEntity.getTerms();
//清空旧的查询条件
queryParamEntity.setTerms(new ArrayList<>());
//添加一个查询条件
queryParamEntity
.where(RecordCreationEntity.creatorId, userId)
//客户端提交的参数 作为嵌套参数
.nest().setTerms(oldParam);
} else if (entity instanceof RecordCreationEntity) {
((RecordCreationEntity) entity).setCreatorId(userId);
} else {
logger.warn("try validate query access,but entity not support, QueryParamEntity and RecordCreationEntity support now!");
}
} else {
Object result = InvokeResultUtils.convertRealResult(context.getParamContext().getInvokeResult());
return matchCreatorId(result, userId);
}
return true;
}
@SuppressWarnings("all")
protected boolean matchCreatorId(Object result, String userId) {
if (null == result) {
return true;
}
if (entity instanceof QueryParamEntity) {
QueryParamEntity queryParamEntity = ((QueryParamEntity) entity);
//重构查询条件
//如: 旧的条件为 where name =? or name = ?
//重构后为: where creatorId=? and (name = ? or name = ?)
List<Term> oldParam = queryParamEntity.getTerms();
//清空旧的查询条件
queryParamEntity.setTerms(new ArrayList<>());
//添加一个查询条件
queryParamEntity
.where(RecordCreationEntity.creatorId,context.getAuthentication().getUser().getId())
//客户端提交的参数 作为嵌套参数
.nest().setTerms(oldParam);
} else if (entity instanceof RecordCreationEntity) {
((RecordCreationEntity) entity).setCreatorId(context.getAuthentication().getUser().getId());
if (result instanceof RecordCreationEntity) {
return userId.equals(((RecordCreationEntity) result).getCreatorId());
} else if (result instanceof Collection) {
Collection<?> collection = ((Collection) result);
//删掉不能访问的对象
collection.removeAll(collection.stream().filter((Object o) -> !matchCreatorId(o, userId))
.collect(Collectors.toList()));
} else {
logger.warn("try validate query access,but entity not support, QueryParamEntity and RecordCreationEntity support now!");
try {
return userId.equals(PropertyUtils.getProperty(result, "creatorId"));
} catch (Exception ignore) {
}
}
return true;
}

View File

@@ -11,8 +11,6 @@ import org.hswebframework.web.authorization.access.ScriptDataAccessConfig;
import org.hswebframework.web.authorization.define.AuthorizingContext;
/**
* TODO 完成注释
*
* @author zhouhao
*/
public class ScriptDataAccessHandler implements DataAccessHandler {

View File

@@ -0,0 +1,215 @@
package org.hswebframework.web.authorization;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.*;
import org.hswebframework.web.authorization.annotation.Authorize;
import org.hswebframework.web.authorization.annotation.RequiresDataAccess;
import org.hswebframework.web.authorization.basic.aop.AopMethodAuthorizeDefinitionParser;
import org.hswebframework.web.authorization.basic.aop.DefaultAopMethodAuthorizeDefinitionParser;
import org.hswebframework.web.authorization.basic.handler.DefaultAuthorizingHandler;
import org.hswebframework.web.authorization.basic.handler.access.DefaultDataAccessController;
import org.hswebframework.web.authorization.define.AuthorizeDefinition;
import org.hswebframework.web.authorization.define.AuthorizingContext;
import org.hswebframework.web.authorization.define.Phased;
import org.hswebframework.web.authorization.simple.*;
import org.hswebframework.web.boost.aop.context.MethodInterceptorContext;
import org.hswebframework.web.commons.entity.param.QueryParamEntity;
import org.hswebframework.web.controller.message.ResponseMessage;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.util.*;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class AuthorizeDefinitionTests {
@Mock
private MethodInterceptorContext queryById;
@Mock
private MethodInterceptorContext dynamicQuery;
@Mock
private Authentication authentication;
AopMethodAuthorizeDefinitionParser parser = new DefaultAopMethodAuthorizeDefinitionParser();
@Before
public void init() throws NoSuchMethodException {
TestClass testClass = new TestClass();
QueryParamEntity entity = new QueryParamEntity();
entity.where("id", "admin").or("name", "admin");
User user = User.builder().name("test").id("test")
.orgId("400000")
.password("admin").salt("1234").build();
//mock MethodInterceptorContext
when(queryById.getMethod()).thenReturn(TestClass.class.getMethod("queryById", String.class));
when(queryById.getTarget()).thenReturn(testClass);
when(queryById.getParameter("id")).thenReturn(Optional.of("test"));
when(queryById.getParams()).thenReturn(Collections.singletonMap("id", "test"));
when(queryById.getInvokeResult()).thenReturn(ResponseMessage.ok(user));
//mock MethodInterceptorContext
when(dynamicQuery.getMethod()).thenReturn(TestClass.class.getMethod("dynamicQuery", QueryParamEntity.class));
when(dynamicQuery.getTarget()).thenReturn(testClass);
when(dynamicQuery.getParams()).thenReturn(Collections.singletonMap("paramEntity", entity));
when(dynamicQuery.getParameter("paramEntity")).thenReturn(Optional.of(entity));
//过滤字段
AbstractDataAccessConfig fieldFilter = new SimpleFieldFilterDataAccessConfig("password", "salt");
fieldFilter.setAction(Permission.ACTION_QUERY);
SimpleFiledScopeDataAccessConfig filedScope = new SimpleFiledScopeDataAccessConfig();
filedScope.setAction(Permission.ACTION_QUERY);
filedScope.setField("orgId");
filedScope.setScopeType("org");
filedScope.setScope(Collections.singleton("400000"));
//mock authentication
when(authentication.getUser()).thenReturn(SimpleUser.builder().id("admin").name("admin").build());
when(authentication.getPermissions()).thenReturn(Arrays.asList(SimplePermission.builder()
.id("test")
.dataAccesses(new HashSet<>(Arrays.asList(fieldFilter, filedScope)))
.actions(new HashSet<>(Arrays.asList(Permission.ACTION_QUERY, Permission.ACTION_UPDATE))).build()));
}
@Test
public void testParseAuthorizeDefinition() {
AuthorizeDefinition definition = parser.parse(queryById);
Assert.assertNotNull(definition);
Assert.assertEquals(definition.getPermissions().size(), 1);
Assert.assertEquals(definition.getPermissions().iterator().next(), "test");
Assert.assertEquals(definition.getActions().iterator().next(), Permission.ACTION_QUERY);
}
@Test
public void testAuthorizingHandler() {
DefaultAuthorizingHandler handler = new DefaultAuthorizingHandler();
AuthorizeDefinition definition = parser.parse(queryById);
AuthorizingContext authorizingContext = new AuthorizingContext();
authorizingContext.setAuthentication(authentication);
authorizingContext.setDefinition(definition);
authorizingContext.setParamContext(queryById);
handler.handle(authorizingContext);
}
/**
* 测试数据权限控制s
*/
@Test
public void testDynamicQueryDataAccessHandler() {
DefaultAuthorizingHandler handler = new DefaultAuthorizingHandler();
DefaultDataAccessController controller = new DefaultDataAccessController();
handler.setDataAccessController(controller);
AuthorizeDefinition definition = parser.parse(dynamicQuery);
//获取到请求参数
QueryParamEntity entity = dynamicQuery.<QueryParamEntity>getParameter("paramEntity").orElseThrow(NullPointerException::new);
System.out.println(JSON.toJSONString(entity, SerializerFeature.PrettyFormat));
AuthorizingContext authorizingContext = new AuthorizingContext();
authorizingContext.setAuthentication(authentication);
authorizingContext.setDefinition(definition);
authorizingContext.setParamContext(dynamicQuery);
handler.handle(authorizingContext);
System.out.println(JSON.toJSONString(entity, SerializerFeature.PrettyFormat));
Assert.assertTrue(entity.getExcludes().size() == 2);
Assert.assertTrue(entity.getTerms().size() == 2);
Assert.assertTrue(entity.getTerms().get(1).getTerms().size() == 2);
}
/**
* 测试数据权限控制s
*/
@Test
public void testGetDataAccessHandler() {
DefaultAuthorizingHandler handler = new DefaultAuthorizingHandler();
DefaultDataAccessController controller = new DefaultDataAccessController();
handler.setDataAccessController(controller);
AuthorizeDefinition definition = parser.parse(queryById);
//响应结果
Object response = queryById.getInvokeResult();
System.out.println(JSON.toJSONString(response, SerializerFeature.PrettyFormat));
AuthorizingContext authorizingContext = new AuthorizingContext();
authorizingContext.setAuthentication(authentication);
authorizingContext.setDefinition(definition);
authorizingContext.setParamContext(queryById);
handler.handle(authorizingContext);
System.out.println(JSON.toJSONString(response, SerializerFeature.PrettyFormat));
Assert.assertTrue(response instanceof ResponseMessage);
Assert.assertTrue(((User) ((ResponseMessage) response).getResult()).getPassword() == null);
Assert.assertTrue(((User) ((ResponseMessage) response).getResult()).getSalt() == null);
}
@Authorize(permission = "test")
public static class TestClass {
@Authorize(action = Permission.ACTION_QUERY, phased = Phased.after, dataAccess = @RequiresDataAccess)
public ResponseMessage<User> queryById(String id) {
return ResponseMessage.ok();
}
@Authorize(action = Permission.ACTION_QUERY)
@RequiresDataAccess
public void dynamicQuery(QueryParamEntity paramEntity) {
System.out.println(JSON.toJSON(paramEntity));
}
}
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class User {
private String id;
private String name;
private String password;
private String salt;
private String orgId;
}
}