利用註解實現productId校驗

1、註解的使用

@PermRequired(params = {@Param(index = 0)}, biz = PermBizCategory.PRODUCT, role = PermRoleGroup.OWNERANDCHILDANDOEM)
public void xxx(String productId, ...) {
    ...
}

2、註解接口定義


package com.xxx;


import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Retention(RetentionPolicy.RUNTIME)    //表示該註解在運行時期仍可以起作用
@Target({ ElementType.METHOD })    //表示該註解只能應用在方法上
public @interface PermRequired {

	/**
	 * 權限業務分類
	 *
	 * @return
	 */
	PermBizCategory biz() default PermBizCategory.GATEWAY;


	/**
	 * 權限分組
	 * 
	 * @return
	 */
	PermRoleGroup role() default PermRoleGroup.SHARER;

	/**
	 * 權限控制參數
	 *
	 * @return
	 */
	Param[] params() default {};

	/**
	 * 使用新的驗證方式,不再使用之前註解的方式驗證
	 * @see
	 * @return
	 */
	boolean useNewAuth() default false;

}

3、定義參數類型枚舉

package com.xxx;


@AllArgsConstructor
@Getter
public enum PermBizCategory {

	PRODUCT("product", "產品相關業務"),
	;
	private String	value;

	private String	description;

	PermBizCategory(String value, String description) {
		this.value = value;
		this.description = description;
	}

	public String getValue() {
		return value;
	}
}
package com.xxx;


public enum PermRoleGroup {

	OWNER("owner", "擁有者"),
	OWNERANDCHILD("ownerandchild", "擁有者和子帳號"),
	OWNERANDCHILDANDOEM("ownerandchildandoem", "擁有者、子帳號和oem關係所有者"),
    OWNERANDCHILDNOTOPERATION("ownerandchildnotoperate","擁有者和子帳號,但是沒有操作"),
    ;

	private String	value;

	private String	description;

	PermRoleGroup(String value, String description) {
		this.value = value;
		this.description = description;
	}

	public String getValue() {
		return value;
	}
}

4、切面

package com.xxx;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;

@Component
@Aspect
public class PermRequiredAspect {

	@Resource
	private PermVerifierFactory permVerifierFactory;

	@Around("@annotation(com.xxx.PermRequired)")
	public Object handlePermission(ProceedingJoinPoint pjp) throws Throwable {
		MethodSignature signature = (MethodSignature) pjp.getSignature();
		Method method = signature.getMethod();
		Object[] args = pjp.getArgs();
        PermRequired[] permRequireds = method.getAnnotationsByType(PermRequired.class);
        for (PermRequired permRequired : permRequireds){
            PermBizCategory bizCategory = permRequired.biz();

            IPermVerifier permVerifier = permVerifierFactory.getPermVerifier(bizCategory);
            permVerifier.verifyPerm(pjp, args, permRequired);
        }

		Object retVal = pjp.proceed();
		return retVal;
	}

}

5、業務處理工廠類


package com.xxx;

import com.xxx.ProductPermVerifier;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;


@Component
public class PermVerifierFactory implements ApplicationContextAware {

	private ApplicationContext applicationContext;

	public IPermVerifier getPermVerifier(PermBizCategory bizCategory) {
		if (PermBizCategory.PRODUCT.equals(bizCategory)) {
			return applicationContext.getBean("productPermVerifier", ProductPermVerifier.class);
		} else {
			throw new IllegalStateException("unexpected bizCategory");
		}
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}
}

6、Verifier接口及其基類


package com.xxx;

import org.aspectj.lang.ProceedingJoinPoint;


public interface IPermVerifier {

	void verifyPerm(ProceedingJoinPoint pjp, Object[] args, PermRequired permRequired) throws Throwable;

}



package com.xxx;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tuya.atop.client.domain.api.ApiRequestDO;
import ognl.Ognl;
import ognl.OgnlException;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;


public abstract class BasePermVerifier implements IPermVerifier {

	protected static final Logger		logger				= LoggerFactory.getLogger(BasePermVerifier.class);

	protected static final Object		NA					= null;

	protected Object getParamValue(Object[] args, Param param)
			throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, OgnlException {
		int index = param.index();
		if (index < 0 || index >= args.length) {
			return NA;
		}

		ParamType type = param.type();
		if (ParamType.PRIMITIVE == type) {
			return args[index];
		} else if (ParamType.BEAN == type) {
			if (args[index] == null) {
				return NA;
			} else {
				return BeanUtils.getProperty(args[index], param.property());
			}
		} else if (ParamType.JSON == type) {
			if (StringUtils.isBlank((String) args[index])) {
				return NA;
			} else {
				JSONObject jsonObject = JSONObject.parseObject((String) args[index]);
				if (jsonObject != null) {
					return Ognl.getValue(param.property(), jsonObject);
				} else {
					return NA;
				}
			}
		} else if (ParamType.JSONARRAY_STRING == type) {
			if (StringUtils.isBlank((String) args[index])) {
				return NA;
			} else {
				JSONArray jsonArray = JSONObject.parseArray((String) args[index]);
				if (jsonArray != null) {
					return jsonArray;
				} else {
					return NA;
				}
			}
		} else if (ParamType.MAP == type) {
			if (args[index] == null) {
				return NA;
			} else {
				return ((Map) args[index]).get(param.property());
			}
		}
		return null;
	}
}

7、產品業務Verifier


package com.tuya.crius.atop.perm.verifier;

import ognl.OgnlException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.util.List;

@Component
public class ProductPermVerifier extends BasePermVerifier {

	@Override
	public void verifyPerm(ProceedingJoinPoint pjp, Object[] args, PermRequired permRequired) throws Throwable {
		PermBizCategory bizCategory = permRequired.biz();
		if (PermBizCategory.PRODUCT.equals(bizCategory)) {
			Param[] params = permRequired.params();
			String productId = (String) getParamValue(args, params[0]);
			checkProductPerm(productId, args, permRequired);
		} else {
			throw new IllegalStateException("unexpected bizCategory");
		}
	}

	protected void checkProductPerm(String productId, Object[] args, PermRequired permRequired)
			throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, OgnlException {
		PermRoleGroup roleGroup = permRequired.role();
		if (PermRoleGroup.OWNER.equals(roleGroup)) {
			...
		} else if (PermRoleGroup.OWNERANDCHILD.equals(roleGroup)) {
			...
		} else if (PermRoleGroup.OWNERANDCHILDNOTOPERATION.equals(roleGroup)) {
            ...
		} else if (PermRoleGroup.OWNERANDCHILDANDOEM.equals(roleGroup)) {
            ...
        }
        else {
			logger.error("check perm deny={unexpected role=" + roleGroup + "}");
			throw new PermissionDeniedException();
		}
	}

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章