You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java方法级授权检查:无Spring实现自定义注解鉴权可行吗?

当然可以!完全不用依赖Spring这类框架,纯Java就能实现你说的这种方法级权限校验注解。我之前就帮朋友做过类似的实现,核心是用到Java的反射和动态代理(或者运行时反射校验),下面给你一步步拆解实现思路和代码示例:

第一步:定义自定义权限注解

首先我们要先定义一个像@AccessValidator这样的注解,指定它可以作用在方法上,并且是运行时可见的:

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

// 权限级别枚举
enum AccessLevel {
    ADMIN, USER, GUEST
}

// 自定义权限校验注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessValidator {
    AccessLevel value();
}
第二步:实现权限校验的核心逻辑

接下来写一个工具类,负责读取方法上的注解,并且和当前用户的权限做对比:

public class AccessCheckUtil {
    // 模拟获取当前登录用户的权限(实际项目里可以从ThreadLocal、上下文等地方拿)
    private static AccessLevel getCurrentUserAccessLevel() {
        // 这里只是示例,实际要替换成真实的用户权限获取逻辑
        return AccessLevel.USER;
    }

    // 校验方法权限的核心方法
    public static void checkAccess(Method method) throws SecurityException {
        // 判断方法上是否有AccessValidator注解
        if (method.isAnnotationPresent(AccessValidator.class)) {
            AccessValidator annotation = method.getAnnotation(AccessValidator.class);
            AccessLevel requiredLevel = annotation.value();
            AccessLevel currentLevel = getCurrentUserAccessLevel();

            // 这里简单做级别判断,实际可以扩展更复杂的权限规则
            if (!currentLevel.equals(requiredLevel)) {
                throw new SecurityException("权限不足:需要" + requiredLevel + "权限,当前是" + currentLevel);
            }
        }
    }
}
第三步:两种调用方式(手动/自动)

方式一:手动调用校验(简单直接)

在调用目标方法前,手动触发权限校验:

public class DemoService {
    @AccessValidator(AccessLevel.ADMIN)
    public void adminOnlyMethod() {
        System.out.println("执行管理员专属方法");
    }

    public static void main(String[] args) throws Exception {
        DemoService service = new DemoService();
        // 获取目标方法
        Method method = DemoService.class.getMethod("adminOnlyMethod");
        try {
            // 先校验权限
            AccessCheckUtil.checkAccess(method);
            // 校验通过再执行方法
            method.invoke(service);
        } catch (SecurityException e) {
            System.err.println(e.getMessage());
        }
    }
}

运行这段代码会抛出权限不足的异常,因为我们模拟的当前用户是USER级别。

方式二:动态代理自动拦截(更优雅)

如果不想每次都手动写校验,可以用JDK动态代理来实现自动拦截方法调用,自动触发校验:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class AccessProxyHandler implements InvocationHandler {
    private final Object target;

    public AccessProxyHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 先执行权限校验
        AccessCheckUtil.checkAccess(method);
        // 校验通过后执行原方法
        return method.invoke(target, args);
    }

    // 创建代理对象的工具方法
    public static <T> T createProxy(T target) {
        return (T) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new AccessProxyHandler(target)
        );
    }
}

然后定义一个接口和实现类来测试:

public interface DemoService {
    @AccessValidator(AccessLevel.ADMIN)
    void adminOnlyMethod();

    @AccessValidator(AccessLevel.USER)
    void userMethod();
}

public class DemoServiceImpl implements DemoService {
    @Override
    public void adminOnlyMethod() {
        System.out.println("执行管理员专属方法");
    }

    @Override
    public void userMethod() {
        System.out.println("执行普通用户方法");
    }
}

// 测试类
public class ProxyTest {
    public static void main(String[] args) {
        DemoService realService = new DemoServiceImpl();
        DemoService proxyService = AccessProxyHandler.createProxy(realService);

        try {
            proxyService.adminOnlyMethod(); // 会抛出权限不足
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }

        try {
            proxyService.userMethod(); // 可以正常执行
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }
}
额外说明
  • 如果担心反射的性能问题,可以考虑用编译时注解处理器来生成静态代理类,这样就不用在运行时做反射操作了,不过实现起来会复杂一点。
  • 权限规则可以根据实际需求扩展,比如支持多个权限、角色组等,只需要修改AccessCheckUtil里的校验逻辑就行。

这样一套下来,就完全脱离Spring等框架实现了你想要的方法级权限校验。如果还有细节想调整,都可以在这个基础上灵活扩展。

内容的提问来源于stack exchange,提问作者Lasse

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:51:10