AOP实现RBAC权限验证

首先引入AOP的依赖

         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
TokenUtil工具类 

作用:1.通过用户生成token

           2.通过token 验证用户是否登录

           3.通过token获取用户实体类

 

public class TokenUtil {

    private static Map<String, User> tokenMap = new HashMap<>();

    public static String generateToken(User user){
        String token = UUID.randomUUID().toString();
        tokenMap.put(token,user);
        return token;
    }

    public static boolean verify(String token){
        return tokenMap.containsKey(token);
    }

    public static User getUser(String token){
        return tokenMap.get(token);
    }
}

AuthorityAop

作用:在调用方法的时候,拿到HEAD中的token,通过tokenUtil工具类获取用户,并通过连表查询查询到用户的权限字段menu,验证注解中的value是否在用户的权限字段中

@Component
@Aspect
public class AuthorityAop {
    @Autowired
    private HttpServletRequest httpServletRequest;


    //定义切入点   切入点就HasAuth注解标注的地方
    @Pointcut("@annotation(com.example.aoptest.common.annonation.HasAuth)")
    public void AuthorityAopPointCut() {

    }
    //环绕
    @Around("AuthorityAopPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        //在调用方法的时候,拿到HEAD中的token,通过tokenUtil工具类获取用户,并通过连表查询查询到用户的权限字段menu,验证注解中的value是否在用户的权限字段中

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        HasAuth viewRecords = method.getAnnotation(HasAuth.class);
        String idValue = viewRecords.value();
        String token = httpServletRequest.getHeader(GlobalConstant.HEAD_TOKEN);
        User user = TokenUtil.getUser(token);
        Set<String> menuList = user.getMenu();
        if (!menuList.contains(idValue)) {
            throw new RuntimeException("权限不足");
        }
        //执行方法
        return joinPoint.proceed();
    }
}
GlobalConstant        全局变量类
public class GlobalConstant {
    public final static String HEAD_TOKEN="token";
}

aop中直接根据这个全局变量拿就ok了

HasAuth        注解类

@Target(ElementType.METHOD)
@Retention(RUNTIME)
public @interface HasAuth {
    String value() default "";
}

使用注解的时候这样用

@HasAuth(value = "menu1")

在方法前用这个注解,可以通过反射获取注解中的值,在aop中可以把注解中的值当作权限字符串,要求登录的用户有这个字符串权限才能访问

 

Controller

在登录的时候,拿到用户的id,通过用户id查到对应用户的权限字符串,把用户的权限字符串set进用户实体类中,并调用TokenUtil的生成token的方法,生成一串token

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;


    @PostMapping("/login")
    public WebResultJson login(@RequestBody User user){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username",user.getUsername());
        queryWrapper.eq("password",user.getPassword());
        User user1 =  userService.getOne(queryWrapper);
        if(user1!=null){
            Long userId = user1.getId();
            Set<String> menuList= userService.getMenu(userId);
            user1.setMenu(menuList);
            String token = TokenUtil.generateToken(user1);
            return WebResultJson.ok(token);
        }
        return WebResultJson.fail();
    }

    @PostMapping("/test")
    @HasAuth(value = "menu1")
    public WebResultJson test(){
       return WebResultJson.ok("我真厉害!");
    }

}

 

 

 如果不在HEAD中加token

就会报错 

User 用户实体类

@Data
@TableName("user")
public class User {
    @TableId
    private Long id;
    private String username;
    private String password;

    @TableField(exist = false)
    private Set<String> menu;
}

 xml

<?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.example.aoptest.mapper.UserMapper">
    <select id="getMenu" resultType="java.lang.String">
        select menu from user
                             left join user_role on user.id = user_role.user_id
                             left join role_menu on user_role.role_id = role_menu.role_id
                             left join menu on role_menu.menu_id=menu.id
        where user.id =#{userId}
    </select>
</mapper>

mapper

public interface UserMapper extends BaseMapper<User> {
    public Set<String> getMenu(@Param("userId")Long userId);
}

数据库

 

 

 

通过(用户id)   查  (角色id)   根据(角色id)查  (权限id)    

就可以查到对应用户的权限,返回的是Set类型

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值