From 6e87a2e9c2ba2debb9e46254e29dbf764553a6a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johnny=20Miller=20=28=E9=94=BA=E4=BF=8A=29?= Date: Mon, 28 Dec 2020 23:17:50 +0800 Subject: [PATCH] feat($AuthCenter): support admin authorization --- .../RbacReactiveAuthorizationManager.java | 11 ++-- .../WebFluxSecurityConfiguration.java | 3 - .../service/impl/PermissionServiceImpl.java | 23 +++++-- .../authcenter/role/service/RoleService.java | 10 +++ .../role/service/impl/RoleServiceImpl.java | 27 ++++++++ .../universal/domain/PermissionType.java | 62 ------------------- .../application-development-local.yml | 4 ++ ...GetPermissionListByRoleIdListResponse.java | 2 +- .../authcenter/permission/PermissionType.java | 12 ++-- .../configuration/MafConfiguration.java | 2 +- .../configuration/MafAutoConfiguration.java | 5 +- .../configuration/MafConfiguration.java | 2 +- 12 files changed, 78 insertions(+), 85 deletions(-) delete mode 100644 auth-center/src/main/java/com/jmsoftware/maf/authcenter/universal/domain/PermissionType.java diff --git a/api-gateway/src/main/java/com/jmsoftware/maf/apigateway/security/RbacReactiveAuthorizationManager.java b/api-gateway/src/main/java/com/jmsoftware/maf/apigateway/security/RbacReactiveAuthorizationManager.java index 9c1b3fa8..09916d28 100644 --- a/api-gateway/src/main/java/com/jmsoftware/maf/apigateway/security/RbacReactiveAuthorizationManager.java +++ b/api-gateway/src/main/java/com/jmsoftware/maf/apigateway/security/RbacReactiveAuthorizationManager.java @@ -58,11 +58,11 @@ public Mono check(Mono authentication, Au .filter(role -> StrUtil.equals("admin", role.getName())) .map(GetRoleListByUserIdResponse.Role::getId).collectList() .switchIfEmpty(getRoleListByUserIdResponseFlux - .map(GetRoleListByUserIdResponse.Role::getId) - .collectList()); + .map(GetRoleListByUserIdResponse.Role::getId) + .collectList()); // Get permission list based on the Mono> - // TODO: auth-center should respond /** for role "admin" + // auth-center will respond /** for role "admin" Mono getPermissionListByRoleIdListResponseMono = roleIdListMono.flatMap( roleIdList -> { GetPermissionListByRoleIdListPayload payload = new GetPermissionListByRoleIdListPayload(); @@ -82,14 +82,15 @@ public Mono check(Mono authentication, Au val path = request.getURI().getPath(); val userPrincipal = mapper.getT2(); for (val buttonPermission : buttonPermissionList) { + // FIXME: currently, the `method` in permission is useless if (antPathMatcher.match(buttonPermission.getUrl(), path)) { log.info("Authorization success! Resource [{}] {} is accessible for user(username: {})", - request.getMethod(), request.getURI(), userPrincipal.getUsername()); + request.getMethod(), request.getURI(), userPrincipal.getUsername()); return new AuthorizationDecision(true); } } log.warn("Authorization failure! Resource [{}] {} is inaccessible for user(username: {})", - request.getMethod(), request.getURI(), userPrincipal.getUsername()); + request.getMethod(), request.getURI(), userPrincipal.getUsername()); return new AuthorizationDecision(false); }); } diff --git a/api-gateway/src/main/java/com/jmsoftware/maf/apigateway/security/WebFluxSecurityConfiguration.java b/api-gateway/src/main/java/com/jmsoftware/maf/apigateway/security/WebFluxSecurityConfiguration.java index 8e4cda9a..48872c26 100644 --- a/api-gateway/src/main/java/com/jmsoftware/maf/apigateway/security/WebFluxSecurityConfiguration.java +++ b/api-gateway/src/main/java/com/jmsoftware/maf/apigateway/security/WebFluxSecurityConfiguration.java @@ -10,7 +10,6 @@ import org.springframework.security.authentication.ReactiveAuthenticationManager; import org.springframework.security.authorization.ReactiveAuthorizationManager; import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; -import org.springframework.security.config.web.server.SecurityWebFiltersOrder; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.crypto.factory.PasswordEncoderFactories; import org.springframework.security.crypto.password.PasswordEncoder; @@ -63,8 +62,6 @@ SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http, .authenticationEntryPoint(serverAuthenticationEntryPoint) .accessDeniedHandler(serverAccessDeniedHandler) .and() - // TODO: this filter might be useless, since its order is -500 - .addFilterBefore(accessLogFilter, SecurityWebFiltersOrder.AUTHENTICATION) // Authentication .authenticationManager(reactiveAuthenticationManager) .securityContextRepository(serverSecurityContextRepository) diff --git a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/permission/service/impl/PermissionServiceImpl.java b/auth-center/src/main/java/com/jmsoftware/maf/authcenter/permission/service/impl/PermissionServiceImpl.java index e7ba0697..8cfbc9a6 100644 --- a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/permission/service/impl/PermissionServiceImpl.java +++ b/auth-center/src/main/java/com/jmsoftware/maf/authcenter/permission/service/impl/PermissionServiceImpl.java @@ -9,11 +9,13 @@ import com.jmsoftware.maf.authcenter.permission.entity.PermissionPersistence; import com.jmsoftware.maf.authcenter.permission.mapper.PermissionMapper; import com.jmsoftware.maf.authcenter.permission.service.PermissionService; +import com.jmsoftware.maf.authcenter.role.service.RoleService; import com.jmsoftware.maf.authcenter.universal.configuration.ProjectProperty; import com.jmsoftware.maf.common.bean.ResponseBodyBean; import com.jmsoftware.maf.common.domain.authcenter.permission.GetPermissionListByRoleIdListPayload; import com.jmsoftware.maf.common.domain.authcenter.permission.GetPermissionListByRoleIdListResponse; import com.jmsoftware.maf.common.domain.authcenter.permission.GetPermissionListByUserIdResponse; +import com.jmsoftware.maf.common.domain.authcenter.permission.PermissionType; import com.jmsoftware.maf.common.domain.springbootstarter.HttpApiResourcesResponse; import com.jmsoftware.maf.common.exception.BusinessException; import lombok.NonNull; @@ -42,17 +44,28 @@ @Service @RequiredArgsConstructor public class PermissionServiceImpl extends ServiceImpl implements PermissionService { + private final RoleService roleService; private final DiscoveryClient discoveryClient; private final ProjectProperty projectProperty; private final RestTemplate restTemplate; @Override public GetPermissionListByRoleIdListResponse getPermissionListByRoleIdList(@Valid GetPermissionListByRoleIdListPayload payload) { - val permissionList = this.getPermissionListByRoleIdList(payload.getRoleIdList()); + val adminRole = roleService.checkAdmin(payload.getRoleIdList()); val response = new GetPermissionListByRoleIdListResponse(); + if (adminRole) { + log.warn("Admin role checked. The role can access any resources"); + val permission = new GetPermissionListByRoleIdListResponse.Permission(); + permission.setUrl("/**"); + permission.setType(PermissionType.BUTTON.getType()); + permission.setPermissionExpression("admin-permission"); + permission.setMethod("*"); + response.getPermissionList().add(permission); + return response; + } + val permissionList = this.getPermissionListByRoleIdList(payload.getRoleIdList()); permissionList.forEach(permissionPersistence -> { - GetPermissionListByRoleIdListResponse.Permission permission = - new GetPermissionListByRoleIdListResponse.Permission(); + val permission = new GetPermissionListByRoleIdListResponse.Permission(); BeanUtil.copyProperties(permissionPersistence, permission); response.getPermissionList().add(permission); }); @@ -91,7 +104,7 @@ public GetServicesInfoResponse getServicesInfo() throws BusinessException { val response = new GetServicesInfoResponse(); val mapper = new ObjectMapper(); val ignoredServiceIdList = Lists.newArrayList(projectProperty.getProjectArtifactId(), - "api-gateway", "spring-boot-admin"); + "api-gateway", "spring-boot-admin"); log.info("Ignored service ID list: {}", ignoredServiceIdList); for (String serviceId : serviceIdList) { if (ignoredServiceIdList.contains(serviceId)) { @@ -104,7 +117,7 @@ public GetServicesInfoResponse getServicesInfo() throws BusinessException { val data = Optional.of(responseBodyBean.getData()) .orElseThrow(() -> new BusinessException("HttpApiResourcesResponse mustn't be null")); HttpApiResourcesResponse httpApiResourcesResponse = mapper.convertValue(data, - HttpApiResourcesResponse.class); + HttpApiResourcesResponse.class); GetServicesInfoResponse.ServiceInfo serviceInfo = new GetServicesInfoResponse.ServiceInfo(); serviceInfo.setServiceId(serviceId); serviceInfo.setHttpApiResources(httpApiResourcesResponse); diff --git a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/role/service/RoleService.java b/auth-center/src/main/java/com/jmsoftware/maf/authcenter/role/service/RoleService.java index 44a439e1..3f8d3e3e 100644 --- a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/role/service/RoleService.java +++ b/auth-center/src/main/java/com/jmsoftware/maf/authcenter/role/service/RoleService.java @@ -6,6 +6,8 @@ import lombok.NonNull; import org.springframework.validation.annotation.Validated; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.util.List; /** @@ -33,4 +35,12 @@ public interface RoleService extends IService { * @return the role list by user id */ List getRoleListByUserId(@NonNull Long userId); + + /** + * Check admin boolean. + * + * @param roleIdList the role id list + * @return the boolean + */ + boolean checkAdmin(@NotEmpty List<@NotNull Long> roleIdList); } diff --git a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/role/service/impl/RoleServiceImpl.java b/auth-center/src/main/java/com/jmsoftware/maf/authcenter/role/service/impl/RoleServiceImpl.java index ee7bb0e5..bb364894 100644 --- a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/role/service/impl/RoleServiceImpl.java +++ b/auth-center/src/main/java/com/jmsoftware/maf/authcenter/role/service/impl/RoleServiceImpl.java @@ -1,16 +1,25 @@ package com.jmsoftware.maf.authcenter.role.service.impl; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.jmsoftware.maf.authcenter.role.entity.RolePersistence; import com.jmsoftware.maf.authcenter.role.mapper.RoleMapper; import com.jmsoftware.maf.authcenter.role.service.RoleService; import com.jmsoftware.maf.common.domain.authcenter.role.GetRoleListByUserIdResponse; +import com.jmsoftware.maf.springbootstarter.configuration.MafConfiguration; import lombok.NonNull; +import lombok.RequiredArgsConstructor; import lombok.val; import org.springframework.stereotype.Service; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.util.List; +import java.util.stream.Collectors; /** *

RoleServiceImpl

@@ -21,7 +30,10 @@ * @date 2020-05-10 22:39:50 */ @Service +@RequiredArgsConstructor public class RoleServiceImpl extends ServiceImpl implements RoleService { + private final MafConfiguration mafConfiguration; + @Override public GetRoleListByUserIdResponse getRoleList(Long userId) { val roleList = this.getRoleListByUserId(userId); @@ -38,4 +50,19 @@ public GetRoleListByUserIdResponse getRoleList(Long userId) { public List getRoleListByUserId(@NonNull Long userId) { return this.getBaseMapper().selectRoleListByUserId(userId); } + + @Override + public boolean checkAdmin(@NotEmpty List<@NotNull Long> roleIdList) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.select(RolePersistence::getName) + .in(RolePersistence::getId, roleIdList); + val rolePersistenceList = this.list(wrapper); + val roleNameSet = rolePersistenceList + .stream() + .map(RolePersistence::getName) + .filter(roleName -> StrUtil.equals(mafConfiguration.getSuperUserRole(), roleName)) + .collect(Collectors.toSet()); + // If roleNameSet is not empty (contains "admin") + return CollUtil.isNotEmpty(roleNameSet); + } } diff --git a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/universal/domain/PermissionType.java b/auth-center/src/main/java/com/jmsoftware/maf/authcenter/universal/domain/PermissionType.java deleted file mode 100644 index 872b90b0..00000000 --- a/auth-center/src/main/java/com/jmsoftware/maf/authcenter/universal/domain/PermissionType.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.jmsoftware.maf.authcenter.universal.domain; - -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; - -/** - *

PermissionType

- *

Change description here

- * - * @author Johnny Miller (锺俊), email: johnnysviva@outlook.com - * @date 2019-05-25 10:24 - **/ -@Slf4j -@Getter -public enum PermissionType { - /** - * Controller - */ - CONTROLLER(0, "Controller"), - /** - * Page - */ - PAGE(1, "Page"), - /** - * Button - */ - BUTTON(2, "Button (API)"); - - private final Integer type; - private final String description; - - PermissionType(Integer type, String description) { - this.type = type; - this.description = description; - } - - public static PermissionType getByType(Integer type) { - PermissionType permissionType = null; - PermissionType[] values = PermissionType.values(); - for (PermissionType pt : values) { - if (pt.getType().equals(type)) { - permissionType = pt; - } - } - return permissionType; - } - - /** - * Get enum by name - * - * @param name enum name - * @return enum - */ - public static PermissionType getByName(String name) { - try { - return PermissionType.valueOf(name); - } catch (IllegalArgumentException e) { - log.error("Invalid enum name: {}", name, e); - return null; - } - } -} diff --git a/auth-center/src/main/resources/application-development-local.yml b/auth-center/src/main/resources/application-development-local.yml index 1d823cd6..e67884a8 100644 --- a/auth-center/src/main/resources/application-development-local.yml +++ b/auth-center/src/main/resources/application-development-local.yml @@ -45,3 +45,7 @@ sftp: private-key-pass-phrase: session-cache-size: 20 session-wait-timeout: 15000 + +maf: + configuration: + web-request-log-disabled: false diff --git a/common/src/main/java/com/jmsoftware/maf/common/domain/authcenter/permission/GetPermissionListByRoleIdListResponse.java b/common/src/main/java/com/jmsoftware/maf/common/domain/authcenter/permission/GetPermissionListByRoleIdListResponse.java index 2da56dec..6f6fd3df 100644 --- a/common/src/main/java/com/jmsoftware/maf/common/domain/authcenter/permission/GetPermissionListByRoleIdListResponse.java +++ b/common/src/main/java/com/jmsoftware/maf/common/domain/authcenter/permission/GetPermissionListByRoleIdListResponse.java @@ -29,7 +29,7 @@ public static class Permission { /** * The Type. */ - private Integer type; + private Byte type; /** * The Permission expression. */ diff --git a/common/src/main/java/com/jmsoftware/maf/common/domain/authcenter/permission/PermissionType.java b/common/src/main/java/com/jmsoftware/maf/common/domain/authcenter/permission/PermissionType.java index e669c455..ceac22bd 100644 --- a/common/src/main/java/com/jmsoftware/maf/common/domain/authcenter/permission/PermissionType.java +++ b/common/src/main/java/com/jmsoftware/maf/common/domain/authcenter/permission/PermissionType.java @@ -16,25 +16,25 @@ public enum PermissionType { /** * Controller */ - CONTROLLER(0, "Controller"), + CONTROLLER(Byte.valueOf("0"), "Controller"), /** * Page */ - PAGE(1, "Page"), + PAGE(Byte.valueOf("1"), "Page"), /** * Button */ - BUTTON(2, "Button (API)"); + BUTTON(Byte.valueOf("2"), "Button (API)"); - private final Integer type; + private final Byte type; private final String description; - PermissionType(Integer type, String description) { + PermissionType(Byte type, String description) { this.type = type; this.description = description; } - public static PermissionType getByType(Integer type) { + public static PermissionType getByType(Byte type) { PermissionType permissionType = null; PermissionType[] values = PermissionType.values(); for (PermissionType pt : values) { diff --git a/reactive-spring-boot-starter/src/main/java/com/jmsoftware/maf/reactivespringbootstarter/configuration/MafConfiguration.java b/reactive-spring-boot-starter/src/main/java/com/jmsoftware/maf/reactivespringbootstarter/configuration/MafConfiguration.java index 1721918e..fe260ecb 100644 --- a/reactive-spring-boot-starter/src/main/java/com/jmsoftware/maf/reactivespringbootstarter/configuration/MafConfiguration.java +++ b/reactive-spring-boot-starter/src/main/java/com/jmsoftware/maf/reactivespringbootstarter/configuration/MafConfiguration.java @@ -31,7 +31,7 @@ public class MafConfiguration { * persistent in database.

*/ @NotBlank - private String superUser = "admin"; + private String superUserRole = "admin"; /** * Ignore URLs */ diff --git a/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/configuration/MafAutoConfiguration.java b/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/configuration/MafAutoConfiguration.java index 766b2c47..ab98f7d0 100644 --- a/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/configuration/MafAutoConfiguration.java +++ b/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/configuration/MafAutoConfiguration.java @@ -9,6 +9,7 @@ import com.jmsoftware.maf.springbootstarter.helper.HttpApiScanHelper; import com.jmsoftware.maf.springbootstarter.helper.IpHelper; import lombok.extern.slf4j.Slf4j; +import lombok.val; import org.springframework.boot.autoconfigure.AutoConfigureOrder; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -48,7 +49,9 @@ public void postConstruct() { @ConditionalOnMissingBean public MafConfiguration mafConfiguration() { log.warn("Initial bean: {}", MafConfiguration.class.getSimpleName()); - return new MafConfiguration(); + val mafConfiguration = new MafConfiguration(); + log.warn("{}", mafConfiguration); + return mafConfiguration; } @Bean diff --git a/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/configuration/MafConfiguration.java b/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/configuration/MafConfiguration.java index cf434c75..6c687d37 100644 --- a/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/configuration/MafConfiguration.java +++ b/spring-boot-starter/src/main/java/com/jmsoftware/maf/springbootstarter/configuration/MafConfiguration.java @@ -31,7 +31,7 @@ public class MafConfiguration { * persistent in database.

*/ @NotBlank - private String superUser = "admin"; + private String superUserRole = "admin"; /** * Ignore URLs, used by web access log filter and web security. */