首页 > 其他分享 >利用注解和 AOP 实现权限认证:原理、实践与代码解析

利用注解和 AOP 实现权限认证:原理、实践与代码解析

时间:2024-12-03 21:33:46浏览次数:6  
标签:org AOP example import 注解 权限 annotation

目录

利用注解和 AOP 实现权限认证:原理、实践与代码解析

一、核心思想

二、目录

三、代码示例

(一)项目搭建与依赖引入(基于 Spring Boot)

(二)自定义权限注解

(三)AOP 切面类实现

(四)远程权限服务接口(Feign 示例)

(五)在业务方法中应用注解


一、核心思想

在现代软件开发中,权限认证是保障系统安全与数据隐私的关键环节。使用注解和 AOP(面向切面编程)实现权限认证,背后蕴含着高效、解耦且可复用的设计理念。

其核心在于将权限验证逻辑从业务方法主体中抽离出来,通过自定义注解作为 “标记”,精准地标注在那些需要进行权限管控的类或方法上。这些注解就像是一个个小巧的 “信号灯”,直观地告知系统此处存在权限要求。而 AOP 则扮演着 “交通警察” 的角色,基于切面机制,在系统运行期间 “拦截” 到带有特定注解标识的方法执行点。一旦拦截成功,切面类便会利用反射等技术获取注解中的权限信息,并结合当前用户的权限数据(往往通过如会话、数据库查询等方式取得)展开细致入微的比对校验。若用户具备相应权限,业务流程顺畅无阻,方法正常执行;反之,当权限缺失,立刻阻断执行并抛出异常或返回特定错误提示,以此确保系统操作严格遵循权限规则,避免非法访问,维护系统的 “秩序井然”。

二、目录

  1. 基础概念剖析
    • 注解(Annotation)简介与应用场景
    • AOP 原理与常见实现框架(如 AspectJ)概览
    • 权限认证基础模型与关键要素
  2. 技术选型与环境搭建
    • 基于 Spring Boot 的项目搭建(引入必要依赖)
    • 配置 AOP 相关组件与注解处理器
  3. 自定义权限注解设计
    • 定义注解结构(元注解配置、属性设定)
    • 注解在业务代码中的应用实例
  4. AOP 切面实现权限验证逻辑
    • 切面类搭建(标注@Aspect等关键注解)
    • 环绕通知(Around)拦截方法并校验权限流程
    • 异常处理与错误反馈机制
  5. 用户权限数据获取与管理
    • 数据库设计思路(存储用户、角色、权限关系)
    • 从数据源(数据库、缓存等)获取用户权限集合
  6. 测试与验证
    • 编写单元测试用例验证权限认证机制有效性
    • 集成测试确保在系统整体流程中权限管控无误
  7. 优化与拓展
    • 性能优化考量(缓存权限数据、优化切面逻辑)
    • 拓展权限模型适应复杂业务场景(多级权限、动态权限)

三、代码示例

(一)项目搭建与依赖引入(基于 Spring Boot)

创建一个 Spring Boot 项目,在pom.xml文件中引入以下核心依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

这里spring-boot-starter-web用于构建 Web 应用,spring-boot-starter-aop提供 AOP 功能支持,lombok简化代码编写(例如自动生成日志对象等)。

(二)自定义权限注解

package com.example.auth.annotation;

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

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface HasPermission {
    String value();
}

这个注解通过@Target指定能作用于类和方法,@Retention设定运行时保留,内部value属性用来承载具体权限标识字符串,比如"user:edit"代表用户编辑权限。

(三)AOP 切面类实现

package com.example.auth.aspect;

import java.lang.reflect.Method;
import java.util.Optional;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.example.auth.annotation.HasPermission;
import com.example.common.constant.Constants;
import com.example.common.exception.ForbiddenException;
import com.example.common.utils.ServletUtils;
import com.example.system.feign.RemotePermissionService;

import lombok.extern.slf4j.Slf4j;

@Aspect
@Component
@Slf4j
public class PermissionAspect {

    @Autowired
    private RemotePermissionService permissionClient;

    @Around("@annotation(com.example.auth.annotation.HasPermission)")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        Signature signature = point.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        HasPermission annotation = method.getAnnotation(HasPermission.class);
        if (annotation == null) {
            return point.proceed();
        }
        String requiredPermission = new StringBuilder(annotation.value()).toString();
        if (hasPermission(requiredPermission)) {
            return point.proceed();
        } else {
            throw new ForbiddenException();
        }
    }

    private boolean hasPermission(String requiredPermission) {
        HttpServletRequest request = ServletUtils.getRequest();
        String tmpUserKey = request.getHeader(Constants.CURRENT_USER_ID);
        if (Optional.ofNullable(tmpUserKey).isPresent()) {
            Long userId = Long.valueOf(tmpUserKey);
            log.debug("userid:{}", userId);
            if (userId == 1L) {
                return true;
            }
            return permissionClient.getPermissionsByUserId(userId).stream().anyMatch(requiredPermission::equals);
        }
        return false;
    }
}

此切面类标注@Aspect表明其切面身份,@Component纳入 Spring 管理。around方法作为环绕通知,拦截带@HasPermission注解的方法,先提取注解权限标识,再通过hasPermission方法校验当前用户(从请求头获取用户 ID,借助RemotePermissionService远程查询权限集)是否具备对应权限,有权限则放行方法执行,否则抛异常阻断。

(四)远程权限服务接口(Feign 示例)

package com.example.system.feign;

import java.util.Set;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import com.example.common.constant.ServiceNameConstants;
import com.example.system.feign.factory.RemotePermissionFallbackFactory;

@FeignClient(name = ServiceNameConstants.PERMISSION_SERVICE, fallbackFactory = RemotePermissionFallbackFactory.class)
public interface RemotePermissionService {
    @GetMapping("permission/perms/{userId}")
    public Set<String> getPermissionsByUserId(@PathVariable("userId") Long userId);
}

定义 Feign 客户端接口,用于与名为ServiceNameConstants.PERMISSION_SERVICE的远程服务交互,按用户 ID 获取权限集,搭配回退工厂实现容错。

(五)在业务方法中应用注解

package com.example.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.example.auth.annotation.HasPermission;

@RestController
public class UserController {

    @HasPermission("user:list")
    @GetMapping("/users")
    public String listUsers() {
        return "用户列表信息";
    }

    @HasPermission("user:edit")
    @GetMapping("/user/edit")
    public String editUser() {
        return "用户编辑操作执行成功";
    }
}

UserControllerlistUserseditUser方法上分别标注@HasPermission注解,赋予不同权限要求,当请求到达对应方法,便触发上述 AOP 权限校验流程。

上述代码完整展示了从基础环境搭建,经自定义注解、切面逻辑编写,到业务应用的整套利用注解和 AOP 实现权限认证的方案,在实际场景中可按需调整优化,保障系统权限管控严密高效。

标签:org,AOP,example,import,注解,权限,annotation
From: https://blog.csdn.net/m0_57836225/article/details/144177293

相关文章

  • 【洛谷】P5738 【深基7.例4】歌唱比赛(详细注解)
    #include<iostream>#include<iomanip>#include<algorithm>usingnamespacestd;intmain(){//定义两个整数变量n和m,用于接收用户输入的二维数组的行数和列数intn,m;cin>>n>>m;//定义二维整数数组A,用于存储用户输入的整数数据//这里......
  • 别让看板成为泄密工具,权限管理比你想象中重要!
    在当今远程办公与在线协作快速普及的时代,企业在选择协作工具时,不仅关注功能和用户体验,安全性也成为一个至关重要的考量因素。然而,很多企业往往忽略了协作看板软件中的“访问权限控制”这一关键点,其实它才是确保数据安全和团队高效运作的核心之一。什么是访问权限控制?简单来说,访......
  • java-自定义日志注解
    ......
  • 基于Java+SSM+JSP学生信息管理系统(源码+LW+调试文档+讲解等)/学生信息/管理系统/学生
    博主介绍......
  • Android App获取root权限
    在Android中,获取root权限通常意味着你需要通过su(superuser)命令来执行具有更高权限的操作。对于系统应用(SystemApp)来说,由于它们具有一定的系统权限,可以访问一些普通应用无法访问的资源,但它们通常并不能直接获得root权限,除非设备已经被root过。要使一个应用程序(特......
  • 如果修改权限后仍然遇到“会话目录写入权限不足”的问题,应该怎么办
    如果修改权限后仍然遇到“会话目录写入权限不足”的问题,可以尝试以下几种方法:检查文件所有者:确保这些目录的文件所有者是Web服务器用户(通常是www-data或apache)。可以使用以下命令检查和修改文件所有者:chown-Rwww-data:www-data/path/to/your/domain/configchown-Rwww-......
  • 【Azure ADLS】为Azure Data Lake Storage的Container赋予了操作权限后创建子文件夹遇
    问题描述在ADF操作StorageAccount(AzureDataLakeStorage),在已经为根Container赋予了权限后,创建子文件夹的时候还是报错403"Thisrequestisnotauthorizedtoperformthisoperationusingthispermission"403  问题解答这是因为ADLSContainer的ACL权限有两......
  • nvm详细安装使用教程(nvm-node多版本管理工具)(此版本需要管理员权限,如需避免请查看新
    1.卸载node(没有安装的可以直接跳过)nvm是一个nodejs的版本管理工具。通过它可以安装和切换不同版本的nodejs,解决node各种版本存在不兼容现象。但在安装之前需要先卸载之前的nodejs1)在控制面版或者应用列表中卸载nodejs2)不行就全局搜索然后删除相关文件2.下载nvm(三个地址......
  • Spring基于注解实现 AOP 切面功能
    前言在SpringAOP(Aspect-OrientedProgramming)中,动态代理是常用的技术之一,用于在运行时动态地为目标对象生成代理对象,并拦截其方法调用。SpringAOP默认使用两种类型的动态代理机制:JDK动态代理和CGLIB代理。‌JDK动态代理‌:JDK动态代理是Java原生提供的动态代理机制,它......
  • 处理 HTTP 请求的注解
    @RequestParam从URL查询参数或表单数据中提取单个参数值。用于GET请求中的查询字符串,或者POST请求中的表单数据URL:/user?id=123&name=John@GetMapping("/user")publicStringgetUser(@RequestParam("id")StringuserId,@RequestParam("name")StringuserName)......