- AOP是什么?
aop是面向切面的编程,是oop的补充,可以统一管理某些事务,如(权限验证、日志、事务管理),通过配置提取共同需求的代码,声明这些代码何时调用,无需修改原始代码。
- 为什么要进行权限鉴定?
当我们开发一个系统时,我们将对不同的用户有不同的操作权限,如管理员和普通用户。普通用户不能调用一些只能由管理员调用的接口。那么系统的安全性就很低了。一般来说,如果需要提高系统的安全性,则需要权限验证。
- 为什么要使用AOP进行权限鉴定?
或者我们在aop的解释中说,aop可以在不修改原始代码的情况下,将共性代码抽离,并通过配置声明何时调用。
- 如何使用AOP进行权限鉴定?
pom.aop依赖于xml导入aop
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
这次我们通过注释来实现aop
首先定义一个权限验证解释
AuthCheck
package com.xc.project.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 权限校验 * @author xc */// 这个注释意味着我们可以在哪些地方使用自定义的注释,ElementType.METHOD表示可以使用该方法@Target(ElementType.METHOD)// 表示注释的生命周期在运行过程中是有效的,因此,可以通过反射获得@Retention(RetentionPolicy.RUNTIME)public @interface AuthCheck { /** * 必须有一定的权限 * * @return */ String mustRole() default "";}
定义权限为UserRoleenum
package com.xc.project.model.enums;import org.apache.commons.lang3.ObjectUtils;import java.util.Arrays;import java.util.List;import java.util.stream.Collectors;/** * 枚举用户角色 * @author xc */public enum UserRoleEnum { USER(用户”, "user"), ADMIN(管理员”, "admin"), BAN(“被封号”, "ban"); private final String text; private final String value; UserRoleEnum(String text, String value) { this.text = text; this.value = value; } /** * 获取值列表 * * @return */ public static List<String> getValues() { return Arrays.stream(values()).map(item -> item.value).collect(Collectors.toList()); } /** * 根据 value 获取枚举 * * @param value * @return */ public static UserRoleEnum getEnumByValue(String value) { if (ObjectUtils.isEmpty(value)) { return null; } for (UserRoleEnum anEnum : UserRoleEnum.values()) { if (anEnum.value.equals(value)) { return anEnum; } } return null; } public String getValue() { return value; } public String getText() { return text; }}
重新定义权限验证aop类
AuthInterceptor
package com.xc.project.aop;import com.xc.project.annotation.AuthCheck;import com.xc.project.common.ErrorCode;import com.xc.project.exception.BusinessException;import com.xc.project.model.enums.UserRoleEnum;import com.xc.project.service.UserService;import com.xc.xcapicommon.model.entity.User;import org.apache.commons.lang3.StringUtils;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.springframework.stereotype.Component;import org.springframework.web.context.request.RequestAttributes;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import javax.annotation.Resource;import javax.servlet.http.HttpServletRequest;/** * 权限校验 AOP * @author xc */// 用于定义一个切面。它将通知编织到目标对象的指定连接点@Aspect// 注册为spring管理的组件@Componentpublic class AuthInterceptor { @Resource private UserService userService; /** * 执行拦截 * * @param joinPoint * @param authCheck * @return */ // 注解Authcheck调用前后完成权限鉴定 @Around("@annotation(authCheck)") public Object doInterceptor(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable { // 首先获得自定义需求权限 String mustRole = authCheck.mustRole(); ///获得当前登录用户 RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes(); HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); User loginUser = userService.getLoginUser(request); // 若权限定义 if (StringUtils.isNotBlank(mustRole)) { // 从自定义的枚举类中获得定义的权限 UserRoleEnum mustUserRoleEnum = UserRoleEnum.getEnumByValue(mustRole); // 若该权限没有定义,则抛出异常 if (mustUserRoleEnum == null) { throw new BusinessException(ErrorCode.NO_AUTH_ERROR); } // 获得当前登录用户的权限 String userRole = loginUser.getUserRole(); // 假如被封号,直接拒绝 if (UserRoleEnum.BAN.equals(mustUserRoleEnum)) { throw new BusinessException(ErrorCode.NO_AUTH_ERROR); } // 必须有管理员的权限 if (UserRoleEnum.ADMIN.equals(mustUserRoleEnum)) { if (!mustRole.equals(userRole)) { throw new BusinessException(ErrorCode.NO_AUTH_ERROR); } } } // 通过权限验证,放行 return joinPoint.proceed(); }}