首先引入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类型