//
// 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;
}