Hzero @Permission注解解析

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package io.choerodon.swagger.annotation;

import io.choerodon.core.iam.ResourceLevel;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.hzero.core.swagger.PermissionStatus;
import org.springframework.http.HttpMethod;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Permission {
    String code() default "";

    String[] roles() default {};

    ResourceLevel level() default ResourceLevel.PROJECT;

    boolean permissionLogin() default false;

    boolean permissionPublic() default false;

    boolean permissionWithin() default false;

    boolean permissionSign() default false;

    String[] tags() default {};

    PermissionStatus[] status() default {PermissionStatus.NONE};

    String upgradeApiPath() default "";

    HttpMethod upgradeApiMethod() default HttpMethod.GET;
}

这个注解与@EnableChoerodonResourceServer注解相结合,去除了security的基本认证,加入了一个JwtTokenFilter过滤器进行用户权限的拦截。并且这个过滤器与@Permission联系起来,通过获取注解的配置来判断是否需要拦截请求

 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest)request;
        String[] var5 = this.skipPath;
        int var6 = var5.length;

        for(int var7 = 0; var7 < var6; ++var7) {
            String path = var5[var7];
            if (path.equals(httpRequest.getRequestURI())) {
                chain.doFilter(request, response);
                return;
            }
        }

        Iterator var14 = this.publicPermissions.iterator();

        while(var14.hasNext()) {
            PublicPermission publicPermission = (PublicPermission)var14.next();
            if (MATCHER.match(publicPermission.path, httpRequest.getRequestURI()) && publicPermission.method.matches(httpRequest.getMethod())) {
                chain.doFilter(request, response);
                return;
            }
        }

        try {
            Authentication authentication = this.tokenExtractor.extract(httpRequest);
            if (authentication == null) {
                if (this.isAuthenticated()) {
                    LOGGER.debug("Clearing security context.");
                    SecurityContextHolder.clearContext();
                }

                LOGGER.debug("No Jwt token in request, will continue chain.");
                ((HttpServletResponse)response).sendError(401, "No Jwt token in request.");
                return;
            }

            request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE, authentication.getPrincipal());
            if (authentication instanceof AbstractAuthenticationToken) {
                AbstractAuthenticationToken needsDetails = (AbstractAuthenticationToken)authentication;
                needsDetails.setDetails(new OAuth2AuthenticationDetails(httpRequest));
            }

            Authentication authResult = this.authenticate(authentication);
            LOGGER.debug("Authentication success: {}", authResult);
            SecurityContextHolder.getContext().setAuthentication(authResult);
            chain.doFilter(request, response);
        } catch (OAuth2Exception var12) {
            LOGGER.debug("Authentication request failed: ", var12);
            ((HttpServletResponse)response).sendError(401, "Invalid JWT token.");
        } finally {
            SecurityContextHolder.clearContext();
        }

    }

@Permission注解的解析主要由ApplicationPermissionParserImpl这个类进行解析

private void findAndParseController() {
        List<PermissionData> permissionDataList = new ArrayList();
        String[] beanNames = this.applicationContext.getBeanNamesForType(Object.class);
        if (ArrayUtils.isNotEmpty(beanNames)) {
            Class<?> beanType = null;
            String[] var4 = beanNames;
            int var5 = beanNames.length;

            for(int var6 = 0; var6 < var5; ++var6) {
                String beanName = var4[var6];
                if (!beanName.startsWith("scopedTarget.")) {
                    try {
                        beanType = this.applicationContext.getType(beanName);
                        if (ClassUtils.isCglibProxyClass(beanType)) {
                            beanType = beanType.getSuperclass();
                        }
                    } catch (Throwable var9) {
                        if (LOGGER.isDebugEnabled()) {
                            LOGGER.debug("Could not resolve target class for bean with name '" + beanName + "'", var9);
                        }
                    }

                    if (Objects.nonNull(beanType) && this.isHandler(beanType)) {
                        permissionDataList.addAll(this.parseController(this.getServiceName(beanType), beanName, beanType));//解析controller
                    }
                }
            }

            this.applicationPermissionRepository.overwrite(permissionDataList);
            this.applicationContext.publishEvent(new ApplicationPermissionParsedEvent(this));
        }

    }

 private List<PermissionData> parseController(String serviceName, String controllerName, Class<?> clazz) {
        LOGGER.debug("Start Parse Service [{}] : Controller [{}] Permission", serviceName, controllerName);
        List<PermissionData> permissionDataList = new ArrayList();
        Api controllerApi = (Api)AnnotatedElementUtils.findMergedAnnotation(clazz, Api.class);
        String resourceCode = this.getResourceCode(controllerApi, clazz.getSimpleName());
        if (StringUtils.isBlank(resourceCode)) {
            LOGGER.warn("Controller's Resource Code Is Empty, Skip Parse Permission");
            return Collections.emptyList();
        } else {
            RequestMapping controllerMapping = (RequestMapping)AnnotatedElementUtils.findMergedAnnotation(clazz, RequestMapping.class);
            String[] controllerPaths = null;
            if (Objects.nonNull(controllerMapping)) {
                controllerPaths = controllerMapping.value();
            }

            if (ArrayUtils.isEmpty(controllerPaths)) {
                controllerPaths = new String[]{""};
            }

            Method[] var9 = clazz.getMethods();
            int var10 = var9.length;

            for(int var11 = 0; var11 < var10; ++var11) {
                Method method = var9[var11];
                permissionDataList.addAll(this.parseMethod(serviceName, method, resourceCode, controllerPaths));//解析方法
            }

            LOGGER.debug("Finished Parse Service [{}] : Controller [{}] Permission", serviceName, controllerName);
            return permissionDataList;
        }
    }
 private List<PermissionData> parseMethod(String serviceName, Method method, String resourceCode, String[] controllerPaths) {
        List<PermissionData> permissionDataList = new ArrayList();
        RequestMapping methodMapping = (RequestMapping)AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class);
        if (Objects.nonNull(methodMapping)) {
            Permission permission = (Permission)AnnotationUtils.findAnnotation(method, Permission.class);
            if (Objects.isNull(permission)) {
                LOGGER.warn("Method [{}.{}] Without @{} Annotation, Use Default Parameters To Define Permission Data", new Object[]{method.getDeclaringClass().getCanonicalName(), method.getName(), Permission.class.getCanonicalName()});
                return Collections.emptyList();
            }

            String[] methodPaths = methodMapping.value();
            if (ArrayUtils.isEmpty(methodPaths)) {
                methodPaths = new String[]{""};
            }

            RequestMethod[] requestMethods = methodMapping.method();
            if (ArrayUtils.isEmpty(requestMethods)) {
                requestMethods = RequestMethod.values();
            }

            ApiOperation operation = (ApiOperation)AnnotationUtils.findAnnotation(method, ApiOperation.class);
            String description = null;
            if (Objects.nonNull(operation)) {
                description = operation.value();
            }

            String methodName = method.getName();
            RequestMethod[] var15 = requestMethods;
            int var16 = requestMethods.length;

            for(int var17 = 0; var17 < var16; ++var17) {
                RequestMethod requestMethod = var15[var17];
                String requestMethodString = requestMethod.name().toLowerCase();
                int index = 0;
                String[] var19 = controllerPaths;
                int var20 = controllerPaths.length;

                for(int var21 = 0; var21 < var20; ++var21) {
                    String controllerPath = var19[var21];
                    String[] var23 = methodPaths;
                    int var24 = methodPaths.length;

                    for(int var25 = 0; var25 < var24; ++var25) {
                        String methodPath = var23[var25];
                        ++index;
                        permissionDataList.add(this.builtPermissionData(serviceName, resourceCode, controllerPaths.length, methodPaths.length, requestMethods.length, description, permission, methodName, requestMethodString, index, controllerPath, methodPath));
                    }
                }
            }
        }

        return permissionDataList;
    }

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
@PermissionData注解是一个自定义注解,它用于在代码中标记需要进行数据隔离的方法。根据引用\[1\]的源代码,该注解可以应用于方法上,并具有以下属性: - code:权限编码,默认为空字符串。 - roles:角色列表,默认为空数组。 - level:资源级别,默认为项目级别。 - permissionLogin:是否需要登录权限,默认为false。 - permissionPublic:是否为公共权限,默认为false。 - permissionWithin:是否为内部权限,默认为false。 - permissionSign:是否为签名权限,默认为false。 - tags:标签列表,默认为空数组。 - status:权限状态列表,默认为PermissionStatus.NONE。 - upgradeApiPath:升级API路径,默认为空字符串。 - upgradeApiMethod:升级API方法,默认为GET方法。 根据引用\[2\]和引用\[3\]的内容,@PermissionData注解可能与数据规则配置和数据隔离有关。它可能用于标记需要进行数据规则配置的方法,并通过拼接SQL语句实现数据隔离的效果。具体的实现方式可能涉及切面和MyBatisPlus的QueryWrapper。 请注意,以上是根据提供的引用内容推测的答案,具体的使用方式和功能可能需要查阅更多相关文档或代码。 #### 引用[.reference_title] - *1* [Hzero @Permission注解解析](https://blog.csdn.net/weixin_43897490/article/details/115207234)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Jeecg如何实现数据权限/隔离?用户上下文变量没有user_id?修改源码](https://blog.csdn.net/ywbbbbb/article/details/121570807)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值