refactor: 优化权限校验逻辑,权限支持*.

This commit is contained in:
zhouhao
2023-09-22 16:29:36 +08:00
parent 51c42c687f
commit 4408fd8e2c
4 changed files with 44 additions and 35 deletions

View File

@@ -93,8 +93,7 @@ public interface Authentication extends Serializable {
* @return 用户持有的权限集合
*/
List<Permission> getPermissions();
default boolean hasDimension(String type, String... id) {
return hasDimension(type, Arrays.asList(id));
}
@@ -113,7 +112,7 @@ public interface Authentication extends Serializable {
}
default Optional<Dimension> getDimension(String type, String id) {
if (StringUtils.isEmpty(type)) {
if (!StringUtils.hasText(type)) {
return Optional.empty();
}
return getDimensions()
@@ -134,7 +133,7 @@ public interface Authentication extends Serializable {
default List<Dimension> getDimensions(String type) {
if (StringUtils.isEmpty(type)) {
if (!StringUtils.hasText(type)) {
return Collections.emptyList();
}
return getDimensions()
@@ -164,7 +163,8 @@ public interface Authentication extends Serializable {
if (null == id) {
return Optional.empty();
}
return getPermissions().stream()
return getPermissions()
.stream()
.filter(permission -> permission.getId().equals(id))
.findAny();
}
@@ -173,17 +173,28 @@ public interface Authentication extends Serializable {
* 判断是否持有某权限以及对权限的可操作事件
*
* @param permissionId 权限id {@link Permission#getId()}
* @param actions 可操作事件 {@link Permission#getActions()} 如果为空,则不判断action,只判断permissionId
* @param actions 可操作动作 {@link Permission#getActions()} 如果为空,则不判断action,只判断permissionId
* @return 是否持有权限
*/
default boolean hasPermission(String permissionId, String... actions) {
return hasPermission(permissionId, Arrays.asList(actions));
return hasPermission(permissionId,
actions.length == 0
? Collections.emptyList()
: Arrays.asList(actions));
}
default boolean hasPermission(String permissionId, Collection<String> actions) {
return getPermission(permissionId)
.filter(permission -> actions.isEmpty() || permission.getActions().containsAll(actions))
.isPresent();
for (Permission permission : getPermissions()) {
if (Objects.equals(permission.getId(), "*")) {
return true;
}
if (Objects.equals(permissionId, permission.getId())) {
return actions.isEmpty()
|| permission.getActions().containsAll(actions)
|| permission.getActions().contains("*");
}
}
return false;
}
/**
@@ -203,11 +214,12 @@ public interface Authentication extends Serializable {
/**
* 设置属性,注意: 此属性可能并不会被持久化,仅用于临时传递信息.
* @param key key
*
* @param key key
* @param value value
*/
default void setAttribute(String key,Serializable value){
getAttributes().put(key,value);
default void setAttribute(String key, Serializable value) {
getAttributes().put(key, value);
}
/**

View File

@@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.collections.CollectionUtils;
import org.hswebframework.web.authorization.Authentication;
import org.hswebframework.web.authorization.Permission;
import org.hswebframework.web.authorization.annotation.Logical;
@@ -62,34 +63,24 @@ public class ResourcesDefinition {
.isPresent();
}
public boolean isEmpty(){
public boolean isEmpty() {
return resources.isEmpty();
}
public boolean hasPermission(Collection<Permission> permissions) {
public boolean hasPermission(Authentication authentication) {
if (CollectionUtils.isEmpty(resources)) {
return true;
}
if (CollectionUtils.isEmpty(permissions)) {
return false;
}
if (permissions.size() == 1) {
return hasPermission(permissions.iterator().next());
}
Map<String, Permission> mappings = permissions.stream().collect(Collectors.toMap(Permission::getId, Function.identity()));
if (logical == Logical.AND) {
return resources.stream()
.allMatch(resource -> Optional.ofNullable(mappings.get(resource.getId()))
.map(per -> resource.hasAction(per.getActions()))
.orElse(false));
return resources
.stream()
.allMatch(resource -> authentication.hasPermission(resource.getId(), resource.getActionIds()));
}
return resources.stream()
.anyMatch(resource -> Optional.ofNullable(mappings.get(resource.getId()))
.map(per -> resource.hasAction(per.getActions()))
.orElse(false));
return resources
.stream()
.anyMatch(resource -> authentication.hasPermission(resource.getId(), resource.getActionIds()));
}
}

View File

@@ -1,6 +1,7 @@
package org.hswebframework.web.authorization.simple;
import lombok.*;
import org.apache.commons.collections.CollectionUtils;
import org.hswebframework.web.authorization.Permission;
import org.hswebframework.web.authorization.access.DataAccessConfig;
@@ -62,4 +63,9 @@ public class SimplePermission implements Permission {
public Permission copy() {
return copy(action -> true, conf -> true);
}
@Override
public String toString() {
return id + (CollectionUtils.isNotEmpty(actions) ? ":" + String.join(",", actions) : "");
}
}

View File

@@ -1,5 +1,6 @@
package org.hswebframework.web.authorization.basic.handler;
import lombok.extern.slf4j.Slf4j;
import org.hswebframework.web.authorization.Authentication;
import org.hswebframework.web.authorization.Permission;
import org.hswebframework.web.authorization.access.DataAccessController;
@@ -17,12 +18,11 @@ import org.springframework.context.ApplicationEventPublisher;
/**
* @author zhouhao
*/
@Slf4j
public class DefaultAuthorizingHandler implements AuthorizingHandler {
private DataAccessController dataAccessController;
private Logger logger = LoggerFactory.getLogger(this.getClass());
private ApplicationEventPublisher eventPublisher;
public DefaultAuthorizingHandler(DataAccessController dataAccessController) {
@@ -69,7 +69,7 @@ public class DefaultAuthorizingHandler implements AuthorizingHandler {
public void handleDataAccess(AuthorizingContext context) {
if (dataAccessController == null) {
logger.warn("dataAccessController is null,skip result access control!");
log.warn("dataAccessController is null,skip result access control!");
return;
}
if (context.getDefinition().getResources() == null) {
@@ -105,7 +105,7 @@ public class DefaultAuthorizingHandler implements AuthorizingHandler {
ResourcesDefinition resources = definition.getResources();
if (!resources.hasPermission(authentication.getPermissions())) {
if (!resources.hasPermission(authentication)) {
throw new AccessDenyException(definition.getMessage(),definition.getDescription());
}
}