springboot+AOP+RBAC自定义权限访问控制03!今天我们做完了整个权限管理的内容。
内容比较多。请大家有足够的耐心看完。
首先。我们为了测试权限的鉴别效果,我们提前准备了一个新闻实体类,对应数据库的tb_news数据表。
我们提前准备好了新闻的管理层控制器,业务层接口,持久层接口等。目的就是为了测试,当角色身份不争取的情况,是否可以请求到这个接口?
下面是验证的整个流程。
导入依赖包:spring-boot-starter-aop
由于我们设置过了parent参数,所以版本号就可以忽略了。
新闻表的内容。很简单。
我们使用了一个产品管理员+vip会员的角色账号,来请求新闻的业务接口。试验一下。我们自定义的权限访问系统能不能生效即可。
package com.yrl.managedemo.aspect;
import com.yrl.managedemo.anno.PreAuthorize;
import com.yrl.managedemo.bean.Role;
import com.yrl.managedemo.bean.User;
import com.yrl.managedemo.service.IUserService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
@Component
@Aspect
public class AuthorizeAspect {
@Autowired
private IUserService userService;
@Autowired
private HttpServletRequest request;
@Autowired
private HttpServletResponse response;
//配置切入点
@Pointcut("@annotation(com.yrl.managedemo.anno.PreAuthorize)")
public void authorizePointCut(){
}
/**
* 后端菜单资源鉴权:
* 1:查询用户的所有接口资源权限列表
* 2:获取当前接口资源的访问权限标识符
* 3:比较
* @param pjp
* @return
* @throws Throwable
*/
@Around("authorizePointCut()")
public Object handle(ProceedingJoinPoint pjp) throws Throwable {
//1:查询用户所有接口的资源权限列表
//从请求头中模拟用户id
String id = request.getHeader("user_id");
List<Role> perms = userService.getOneUserByUserId(Integer.valueOf(id)).get(0).getRoleList();
//2:获取当前接口资源的访问权限标识符
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
PreAuthorize annotation = method.getAnnotation(PreAuthorize.class);
String methodPermission = annotation.value();
//3:比较
boolean result = perms.contains(methodPermission);
//4:如果当前用户没有当前接口的权限,403/抱歉,您无权访问
// if(!result){
// response.setContentType("application/json;charset=UTF-8");
// response.setStatus(403);
// response.getWriter().write("抱歉,您无权访问");
// }
try (ServletOutputStream outputStream = response.getOutputStream()) {
if(!result){
response.setContentType("application/json;charset=UTF-8");
response.setStatus(403);
outputStream.print("抱歉,您权限不够");
}
} catch (IOException ex) {
}
//5:末尾的返回是交付给目标方法。甚至我们还可以拿到它的内容,修改后再交付回去。
return pjp.proceed();
}
}
如图,这个是我们 自定义的一个权限访问类,里面我们已经把它提前做好了配置。
整体思想,就是2大步骤,第一步,定义切入点。第二步,定义好切入点的通知模式。我们这次采用的环绕通知。里面写好了具体的业务判定逻辑。
判定逻辑里面写的很清晰了,不再一一介绍了。
我们定义的鉴权业务类,在这个文件夹下面存放。
如图,我们使用postman接口测试软件来进行接口的调用。
我们在headers里面配置了用户的id,模拟真实的场景。
提交后,我们开启了调试模式。启动了服务器。
逐步排查数据变化情况。F7(按键)一步一个函数的去执行。
如图,我们已经拿到了用户的id为3.查询到了该用户的权限情况。经过判定,不吻合业务要求。所以返回了result为false.意味着当前登录的用户,是无权访问该接口地址的。