前置安排:这里的权限控制使用的是五张 MySQL 表:分别为:
用户表、角色表、权限表、用户角色表(存储用户id和角色id的绑定关系)、角色权限表(存储角色id和权限id的绑定关系)
1、自定义注解,读取自定义的权限码
@Target(ElementType.METHOD) //表示该注解只能用于方法上
@Retention(RetentionPolicy.RUNTIME) //表示注解会在运行时保留
public @interface CheckPermission {
String[] value(); // 定义需要的权限
}
@Aspect
@Component
public class PermissionAspect {
private final PermissionService permissionService;
//private final HttpServletRequest request;
public PermissionAspect(PermissionService permissionService) {
this.permissionService = permissionService;
//this.request = request;
}
@Before("@annotation(checkPermission)")
public void checkUserPermission(JoinPoint joinPoint, CheckPermission checkPermission) throws Exception {
// 从请求头中获取用户ID
//String userIdHeader = request.getHeader("User-Id");
// if (userIdHeader == null) {
// throw new Exception("请求头中未找到 User-Id");
// }
Long userId = Long.parseLong("1");
// 获取注解中所需的权限
String[] requiredPermissions = checkPermission.value();
// 校验用户是否具备指定权限
for (String permission : requiredPermissions) {
System.out.println("permission = " + permission);
if (!permissionService.hasPermission(userId, permission)) {
throw new Exception("用户无权访问: " + permission);
}
}
}
}
注意:在 PermissionAspect 类中,去判断该用户是否拥有此权限。一般是根据用户的 id 传参,用户的id一般是在请求头中获取的,我这里为了方便,把用户的id写死为了 “1”。
@Service
public class PermissionService {
@Autowired
private PermissionMapper permissionMapper;
public boolean hasPermission(Long userId, String permissionName) {
Set<String> userPermissions = permissionMapper.selectPermissionByUserId(userId);
for (String permission : userPermissions) {
if (permission.equals(permissionName)) {
return true;
}
}
return false;
}
}
2、根据用户的id关联查询权限码
@Mapper
public interface PermissionMapper {
Set<String> selectPermissionByUserId(@Param("userId") Long userId);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.soft.mapper.PermissionMapper">
<select id="selectPermissionByUserId" resultType="java.lang.String" parameterType="map">
SELECT p.permission_name
from users u
left join user_role ur on u.id = ur.user_id
left join roles r on ur.role_id = r.id
left join role_permission rp on r.id = rp.role_id
left join permissions p on rp.permission_id = p.id
where u.id = #{userId}
</select>
</mapper>
3、在controller层使用权限校验
@RestController
public class PermissopnController {
//@CheckPermission({"100001", "100002"})
@CheckPermission("100001")
@GetMapping("/hello")
public String test1(){
return "hello world permission";
}
}
注意:该权限码必须是该登录用户拥有的权限码,只有拥有权限码的用户才能访问该接口,如果是多个权限码,可以使用 {"权限码","权限码"} ,在这里多个权限码是并集。