自定义注解实现权限验证

本文介绍了如何在Spring MVC中通过自定义注解实现权限验证。首先,定义了一个`RoleAuthorize`注解,然后创建了一个拦截器`RoleInterceptor`检查请求中的方法或类是否带有权限注解,并根据用户token获取角色ID进行匹配。测试部分展示了如何在学生管理接口上使用注解限制访问权限。
摘要由CSDN通过智能技术生成

一、前言

在我们写项目时,一个项目通常会有拥有不同角色的用户,在进入某个方法前,会判断该用户是否具有此权限,今天我们来用自定义注解实现一下这个功能。

注解参数不懂的小伙伴可以移步这篇文章:java自定义注解_crazyK.的博客-CSDN博客  

二、业务场景

1.场景介绍

假如有一个学生管理系统,我们来对一个用户是否具有对学生管理这个模块操作的权限进行验证

2.数据库

存储用户基本信息的用户表

角色表

用户角色关联表

3.前情提示

在写权限验证之前要把登录功能并传入token,在token里保存登录用户的角色id (后面会用到)

//登录
    @RequestMapping("login")
    public ResultJson login(User user) {
        if (user.getUserName() == null || user.getUserPassword() == null) {
            return ResultJson.error("用户名或密码错误!");
        }
        User userDb = loginService.login(user);
        if (userDb == null) {
            return ResultJson.error("用户名或者密码错误!");
        }

        Long uid = userDb.getId();
        //查询登录用户具有的角色id
        List<Long> roleIdList = loginService.userRoleIdList(uid);
        user.setId(uid);
        user.setRoleIdList(roleIdList);
        //这里设置token
        String token = TokenUtil.genToken(user);
        User user1 = new User();
        user1.setId(userDb.getId());
        user1.setUserName(userDb.getUserName());
        user1.setUserMail(userDb.getUserMail());
        user1.setUserPhone(userDb.getUserPhone());
        user1.setToken(token);
        user1.setRoleIdList(roleIdList);
        user1.setId(userDb.getId());
        return ResultJson.ok(GlobalConstant.RESULT_OK_MSG, user1);
    }

三、编码

1.创建一个自定义注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
/**
 * 权限验证自定义注解
 */
public @interface RoleAuthorize {
    String[] value() default {};
}

2.创建一个拦截器

这个拦截器拦截所有访问路径的url,如果访问方法上带有我们创建的自定义注解RoleAuthoeize,则获取这个注解上限定访问的角色,方法中没有注解在获取这个类是否有这个注解,如果都没有,则这个类没有访问权限限制,放行

@Component
public class RoleInterceptor  extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {
        
        HandlerMethod handlerMethod = (HandlerMethod)handler;
        //在方法上寻找注解(这里是反射)
        RoleAuthorize permission = handlerMethod.getMethodAnnotation(RoleAuthorize.class);
        if (permission == null) {
            //方法不存在则在类上寻找注解则在类上寻找注解
            permission = handlerMethod.getBeanType().getAnnotation(RoleAuthorize.class);
        }

        //如果没有添加权限注解则直接跳过允许访问
        if (permission == null) {
            return true;
        }

        //获取角色id(登录时用户拥有的角色id存储在了token中)
        String token = request.getHeader(GlobalConstant.HEADER_TOKEN);
        Long roleId = TokenUtil.getRoleId(token);
        String roleId2 = String.valueOf(roleId);
        //获取注解中的值
        String[] validateRoles = permission.value();
        for(int i = 1; i < validateRoles.length; i++){
            if (validateRoles[i].equals(roleId2 )){
                return true;
            }
        }
        throw new AccessDeniedException("您没有权限!");
    }
}

3.注册拦截器

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private RoleInterceptor roleInterceptor;
    

    @Override
    public void addInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(roleInterceptor).addPathPatterns("/**");

    }
}

四、测试

1.先写几个简单的方法将自定义注解修饰在方法上(修饰在类上也可以)

//增加
    //value中的值表示只有拥有角色id为1的管理员或id为2的老师才具有对学生信息操作的权限
    @RoleAuthorize(value = {"1","2"})
    @RequestMapping("insert")
    public ResultJson insert(@RequestBody User user) {
            if (studentService.save(user)) {
                studentService.insertUserRole(user.getId());
                return ResultJson.ok(GlobalConstant.RESULT_OK_MSG, user);
            } else {
                return ResultJson.error(GlobalConstant.RESULT_ERROR_MSG);
            }
    }

    //修改
    @RoleAuthorize(value = {"1","2"})
    @RequestMapping("update")
    public ResultJson updateById(@RequestBody User user) {
            if (studentService.updateById(user)) {
                return ResultJson.ok(GlobalConstant.RESULT_OK_MSG, user);
            } else {
                return ResultJson.error(GlobalConstant.RESULT_ERROR_MSG);
            }
    }

    //删除
    @RoleAuthorize(value = {"1","2"})
    @RequestMapping("delete")
    public ResultJson deleteById(Long id) {
            if (studentService.removeById(id)) {
                studentService.deleteUserRole(id);
                return ResultJson.ok(GlobalConstant.RESULT_OK_MSG, id);
            } else {
                return ResultJson.error(GlobalConstant.RESULT_ERROR_MSG);
            }

    }

2.测试

1)先登录

2.调用学生模块的任意一个接口测试

别忘了传入token(要验证用户拥有的角色id) 

 调用接口

 再登录一个只有学生角色的用户

 

 

没有权限 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值