SpringBoot切面實(shí)現(xiàn)token權(quán)限校驗(yàn)詳解
SpringBoot實(shí)現(xiàn)token權(quán)限
數(shù)據(jù)表
要實(shí)現(xiàn)權(quán)限校驗(yàn),首先數(shù)據(jù)表和實(shí)體類上需要有權(quán)限字段,我的表中permission和gender是通過外鍵約束permission表和gender表實(shí)現(xiàn)枚舉的,因?yàn)榭赏卣剐愿?/p>
/* Navicat Premium Data Transfer Source Server : Yan Source Server Type : MySQL Source Server Version : 80027 Source Host : localhost:3306 Source Schema : coc Target Server Type : MySQL Target Server Version : 80027 File Encoding : 65001 Date: 07/05/2023 20:00:45 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` varchar(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '主鍵', `account` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '賬號', `password` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '密碼', `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '姓名', `gender` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '未知' COMMENT '性別', `telephone` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '手機(jī)號', `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '郵箱', `signature` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '無簽名' COMMENT '簽名', `avatar_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT 'C:\\Users\\Yan\\Desktop\\user\\avatar\\avatar.jpg' COMMENT '頭像地址', `permission` int NULL DEFAULT 20 COMMENT '權(quán)限', `banned` bit(1) NULL DEFAULT b'0' COMMENT '是否被封禁', `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '無備注' COMMENT '備注', `create_time` datetime NOT NULL COMMENT '創(chuàng)建時(shí)間', PRIMARY KEY (`id`) USING BTREE, INDEX `f_gender`(`gender` ASC) USING BTREE, INDEX `f_permission`(`permission` ASC) USING BTREE, CONSTRAINT `f_gender` FOREIGN KEY (`gender`) REFERENCES `gender` (`gender_name`) ON DELETE RESTRICT ON UPDATE CASCADE, CONSTRAINT `f_permission` FOREIGN KEY (`permission`) REFERENCES `permission` (`weight`) ON DELETE RESTRICT ON UPDATE CASCADE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; SET FOREIGN_KEY_CHECKS = 1;


使用token
項(xiàng)目使用token校驗(yàn),那么可以通過請求發(fā)送過來的token取到redis緩存中token對應(yīng)的用戶id,因此需要一個(gè)存放token:id的hash表,由于我做的token驗(yàn)證直接從表中取token校驗(yàn),同時(shí)也需要取對應(yīng)的id,所以token和id互為key和value

實(shí)體類
這是我用mybatis-plsu-generator根據(jù)數(shù)據(jù)表自動(dòng)生成的
package com.greenjiao.coc.bean;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.Data;
/**
* <p>
*
* </p>
*
* @author yan
* @since 2023-05-07
*/
@Data
@TableName("user")
public class User {
/**
* 主鍵
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* 賬號
*/
@TableField("account")
private String account;
/**
* 密碼
*/
@TableField("password")
private String password;
/**
* 姓名
*/
@TableField("name")
private String name;
/**
* 性別
*/
@TableField("gender")
private String gender;
/**
* 手機(jī)號
*/
@TableField("telephone")
private String telephone;
/**
* 郵箱
*/
@TableField("email")
private String email;
/**
* 簽名
*/
@TableField("signature")
private String signature;
/**
* 頭像地址
*/
@TableField("avatar_address")
private String avatarAddress;
/**
* 權(quán)限
*/
@TableField("permission")
private Integer permission;
/**
* 是否被封禁
*/
@TableField("banned")
private Boolean banned;
/**
* 備注
*/
@TableField("remark")
private String remark;
/**
* 創(chuàng)建時(shí)間
*/
@TableField("create_time")
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime createTime;
}權(quán)限枚舉類
定義不同權(quán)限身份
package com.greenjiao.coc.common.enumconstant;
/**
* 權(quán)限信息
*/
public enum PERMISSION_TYPE {
BANNED_USER(0, "封禁用戶"),
BLOCKED_SPEECH_USER(10, "禁言用戶"),
NORMAL_USER(20, "普通用戶"),
PREMIUM_USER(30, "高級用戶"),
NORMAL_ADMIN(100, "管理員"),
TOP_ADMIN(999, "最高管理員");
private final Integer weight;
private final String name;
PERMISSION_TYPE(Integer weight, String name) {
this.weight = weight;
this.name = name;
}
public Integer getWeight() {
return weight;
}
public String getName() {
return name;
}
}自定義注解
我們需要對一些控制層中特定的方法進(jìn)行權(quán)限校驗(yàn),并且部分方法的權(quán)限要求可能是不同的,所以需要給方法添加自定義注解,注解中包含所需的權(quán)限
package com.greenjiao.coc.annotation;
import com.greenjiao.coc.common.enumconstant.PERMISSION_TYPE;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 權(quán)限校驗(yàn)注解
*/
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Role {
PERMISSION_TYPE permission() default PERMISSION_TYPE.TOP_ADMIN;
}控制層添加注解
我的用戶的控制層,除了登陸和注冊外,其他的方法都使用自定義注解Role設(shè)置對應(yīng)所需權(quán)限
package com.greenjiao.coc.controller;
import com.greenjiao.coc.annotation.Role;
import com.greenjiao.coc.bean.User;
import com.greenjiao.coc.common.DataVO;
import com.greenjiao.coc.common.enumconstant.PERMISSION_TYPE;
import com.greenjiao.coc.service.impl.UserServiceImpl;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("/coc/user")
public class UserController {
private final UserServiceImpl userService;
public UserController(UserServiceImpl userService) {
this.userService = userService;
}
@PostMapping("/register")
public DataVO<User> register(@RequestBody User user) {
return userService.register(user);
}
@PostMapping("/login")
public DataVO<Map<String, Object>> login(@RequestBody User user) {
return userService.login(user);
}
@Role(permission = PERMISSION_TYPE.NORMAL_USER)
@PutMapping
public DataVO<User> update(@RequestBody User user) {
return userService.update(user);
}
@Role(permission = PERMISSION_TYPE.NORMAL_ADMIN)
@DeleteMapping("/{id}")
public DataVO<User> delete(@PathVariable String id) {
return userService.delete(id);
}
@Role(permission = PERMISSION_TYPE.NORMAL_USER)
@GetMapping
public DataVO<User> selectAll(@RequestBody User user) {
return userService.selectAll(user);
}
}添加控制層切面
添加其中的權(quán)限校驗(yàn)@Before注解指定切點(diǎn)
需要權(quán)限校驗(yàn)的切點(diǎn)為controller包下所有類的所有方法,并且要擁有Role注解
package com.greenjiao.coc.aspect;
import com.alibaba.fastjson2.JSON;
import com.greenjiao.coc.annotation.Role;
import com.greenjiao.coc.bean.User;
import com.greenjiao.coc.common.DataVO;
import com.greenjiao.coc.common.ServerConstants;
import com.greenjiao.coc.exception.ExceptionEnum;
import com.greenjiao.coc.exception.ExceptionTip;
import com.greenjiao.coc.mapper.UserMapper;
import com.greenjiao.coc.util.MyUtil;
import com.greenjiao.coc.util.RedisUtil;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
@Aspect
@Component
public class ControllerAspect {
private final RedisUtil redisUtil;
private final UserMapper userMapper;
public ControllerAspect(RedisUtil redisUtil, UserMapper userMapper) {
this.redisUtil = redisUtil;
this.userMapper = userMapper;
}
// 指定切點(diǎn)為controller目錄中所有類的selectAll方法并且要求攜帶的參數(shù)是Map<String,Object> param
@Pointcut(value = "execution(* com.greenjiao.coc.controller..selectAll(..)) && args(param)", argNames = "param")
public void controllerPoint(Map<String, Object> param) {
}
@Pointcut(value = "execution(* com.greenjiao.coc.controller..*(..)) && @annotation(com.greenjiao.coc.annotation.Role)")
public void controllerCheckRolePoint() {
}
/**
* 將查詢的內(nèi)容統(tǒng)一轉(zhuǎn)為對應(yīng)實(shí)體類
* @param joinPoint
* @param param
* @return
* @throws Throwable
*/
@Around(value = "controllerPoint(param) && args(..)", argNames = "joinPoint,param")
public Object changeParam(ProceedingJoinPoint joinPoint, @RequestBody Map<String, Object> param) throws Throwable {
Integer page = (Integer) param.get(ServerConstants.DEFAULT_PAGE_NAME); //獲得param中用于分頁的page和limit后將其移除,剩余在param中的鍵值對即為需要查詢的條件
param.remove(ServerConstants.DEFAULT_PAGE_NAME);
Integer limit = (Integer) param.get(ServerConstants.DEFAULT_LIMIT_NAME);
param.remove(ServerConstants.DEFAULT_LIMIT_NAME);
String className = MyUtil.getClassName(joinPoint.getTarget().getClass().getName()); //工具類獲取全限定類名
Class<?> clazz = Class.forName(className); //反射機(jī)制創(chuàng)建類
Object obj = JSON.parseObject(JSON.toJSONString(param), clazz); //將Map中剩余的鍵值對轉(zhuǎn)為對應(yīng)類型的json對象
Map<String, Object> params = new HashMap<>(); //重新存放最后需要新返回的參數(shù),procceed方法的參數(shù)需要一個(gè)Object數(shù)組,
params.put(ServerConstants.DEFAULT_BEAN_NAME, obj); //但是controller層中的selectAll方法又只有一個(gè)參數(shù),
params.put(ServerConstants.DEFAULT_PAGE_NAME, page); //如果直接將鍵值對放到Object數(shù)組中將會報(bào)參數(shù)個(gè)數(shù)異常,
params.put(ServerConstants.DEFAULT_LIMIT_NAME, limit); //所以這里將鍵值對放到Map中,再將Map放到Object數(shù)組中
return joinPoint.proceed(new Object[]{params}); //procceed方法的參數(shù)需要一個(gè)Object數(shù)組,
}
/**
* 權(quán)限校驗(yàn)
*/
@Before("controllerCheckRolePoint()")
public void checkRole(JoinPoint joinPoint){
// 獲取Role注解中的permission權(quán)重值
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Role role = method.getAnnotation(Role.class);
Integer requiredWeight = role.permission().getWeight();
// 從redis表中查找token對應(yīng)的id,獲取對應(yīng)的用戶
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String token = request.getHeader("token");
String id = (String) redisUtil.hget(ServerConstants.REDIS_TOKEN_TABLE_NAME, token);
User user = userMapper.selectById(id);
// 校驗(yàn)
if(user.getPermission() < requiredWeight){
throw new ExceptionTip(ExceptionEnum.LOW_PERMISSION);
}
}
}RedisUtil工具類
這是我權(quán)限校驗(yàn)使用的RedisUtil工具類,由于無用的警告太多,看的煩我用@SuppressWarnings注解將所有警告忽略了
并且將其給Spring管理了,所以可以在其他地方自動(dòng)注入
package com.greenjiao.coc.util;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* Redis工具類
*/
@SuppressWarnings("all")
@Component
public class RedisUtil {
@Resource
private RedisTemplate<String, Object> redisTemplate;
/****************** common start ****************/
/**
* 指定緩存失效時(shí)間
*
* @param key 鍵
* @param time 時(shí)間(秒)
* @return
*/
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根據(jù)key 獲取過期時(shí)間
*
* @param key 鍵 不能為null
* @return 時(shí)間(秒) 返回0代表為永久有效
*/
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* 判斷key是否存在
*
* @param key 鍵
* @return true 存在 false不存在
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 刪除緩存
*
* @param key 可以傳一個(gè)值 或多個(gè)
*/
@SuppressWarnings("unchecked")
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
}
}
}
/****************** common end ****************/
/****************** String start ****************/
/**
* 普通緩存獲取
*
* @param key 鍵
* @return 值
*/
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* 普通緩存放入
*
* @param key 鍵
* @param value 值
* @return true成功 false失敗
*/
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通緩存放入并設(shè)置時(shí)間
*
* @param key 鍵
* @param value 值
* @param time 時(shí)間(秒) time要大于0 如果time小于等于0 將設(shè)置無限期
* @return true成功 false 失敗
*/
public boolean set(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 遞增
*
* @param key 鍵
* @param delta 要增加幾(大于0)
* @return
*/
public long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("遞增因子必須大于0");
}
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 遞減
*
* @param key 鍵
* @param delta 要減少幾(小于0)
* @return
*/
public long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("遞減因子必須大于0");
}
return redisTemplate.opsForValue().increment(key, -delta);
}
/****************** String end ****************/
/****************** Map start ****************/
/**
* HashGet
*
* @param key 鍵 不能為null
* @param item 項(xiàng) 不能為null
* @return 值
*/
public Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}
/**
* 獲取hashKey對應(yīng)的所有鍵值
*
* @param key 鍵
* @return 對應(yīng)的多個(gè)鍵值
*/
public Map<Object, Object> hmget(String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* HashSet
*
* @param key 鍵
* @param map 對應(yīng)多個(gè)鍵值
* @return true 成功 false 失敗
*/
public boolean hmset(String key, Map<String, Object> map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* HashSet 并設(shè)置時(shí)間
*
* @param key 鍵
* @param map 對應(yīng)多個(gè)鍵值
* @param time 時(shí)間(秒)
* @return true成功 false失敗
*/
public boolean hmset(String key, Map<String, Object> map, long time) {
try {
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一張hash表中放入數(shù)據(jù),如果不存在將創(chuàng)建
*
* @param key 鍵
* @param item 項(xiàng)
* @param value 值
* @return true 成功 false失敗
*/
public boolean hset(String key, String item, Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一張hash表中放入數(shù)據(jù),如果不存在將創(chuàng)建
*
* @param key 鍵
* @param item 項(xiàng)
* @param value 值
* @param time 時(shí)間(秒) 注意:如果已存在的hash表有時(shí)間,這里將會替換原有的時(shí)間
* @return true 成功 false失敗
*/
public boolean hset(String key, String item, Object value, long time) {
try {
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 刪除hash表中的值
*
* @param key 鍵 不能為null
* @param item 項(xiàng) 可以使多個(gè) 不能為null
*/
public void hdel(String key, Object... item) {
redisTemplate.opsForHash().delete(key, item);
}
/**
* 判斷hash表中是否有該項(xiàng)的值
*
* @param key 鍵 不能為null
* @param item 項(xiàng) 不能為null
* @return true 存在 false不存在
*/
public boolean hHasKey(String key, String item) {
return redisTemplate.opsForHash().hasKey(key, item);
}
/**
* hash遞增 如果不存在,就會創(chuàng)建一個(gè) 并把新增后的值返回
*
* @param key 鍵
* @param item 項(xiàng)
* @param by 要增加幾(大于0)
* @return
*/
public double hincr(String key, String item, long by) {
return redisTemplate.opsForHash().increment(key, item, by);
}
/**
* hash遞減
*
* @param key 鍵
* @param item 項(xiàng)
* @param by 要減少記(小于0)
* @return
*/
public double hdecr(String key, String item, long by) {
return redisTemplate.opsForHash().increment(key, item, -by);
}
/****************** Map end ****************/
/****************** Set start ****************/
/**
* 根據(jù)key獲取Set中的所有值
*
* @param key 鍵
* @return
*/
public Set<Object> sGet(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 根據(jù)value從一個(gè)set中查詢,是否存在
*
* @param key 鍵
* @param value 值
* @return true 存在 false不存在
*/
public boolean sHasKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 將數(shù)據(jù)放入set緩存
*
* @param key 鍵
* @param values 值 可以是多個(gè)
* @return 成功個(gè)數(shù)
*/
public long sSet(String key, Object... values) {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 將set數(shù)據(jù)放入緩存
*
* @param key 鍵
* @param time 時(shí)間(秒)
* @param values 值 可以是多個(gè)
* @return 成功個(gè)數(shù)
*/
public long sSetAndTime(String key, long time, Object... values) {
try {
Long count = redisTemplate.opsForSet().add(key, values);
if (time > 0)
expire(key, time);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 獲取set緩存的長度
*
* @param key 鍵
* @return
*/
public long sGetSetSize(String key) {
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 移除值為value的
*
* @param key 鍵
* @param values 值 可以是多個(gè)
* @return 移除的個(gè)數(shù)
*/
public long setRemove(String key, Object... values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/****************** Set end ****************/
/****************** List start ****************/
/**
* 獲取list緩存的內(nèi)容
*
* @param key 鍵
* @param start 開始
* @param end 結(jié)束 0 到 -1代表所有值
* @return
*/
public List<Object> lGet(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 獲取list緩存的長度
*
* @param key 鍵
* @return
*/
public long lGetListSize(String key) {
try {
return redisTemplate.opsForList().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 通過索引 獲取list中的值
*
* @param key 鍵
* @param index 索引 index>=0時(shí), 0 表頭,1 第二個(gè)元素,依次類推;index<0時(shí),-1,表尾,-2倒數(shù)第二個(gè)元素,依次類推
* @return
*/
public Object lGetIndex(String key, long index) {
try {
return redisTemplate.opsForList().index(key, index);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 將list放入緩存
*
* @param key 鍵
* @param value 值
* @return
*/
public boolean lSet(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 將list放入緩存
*
* @param key 鍵
* @param value 值
* @param time 時(shí)間(秒)
* @return
*/
public boolean lSet(String key, Object value, long time) {
try {
redisTemplate.opsForList().rightPush(key, value);
if (time > 0)
expire(key, time);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 將list放入緩存
*
* @param key 鍵
* @param value 值
* @return
*/
public boolean lSet(String key, List<Object> value) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 將list放入緩存
*
* @param key 鍵
* @param value 值
* @param time 時(shí)間(秒)
* @return
*/
public boolean lSet(String key, List<Object> value, long time) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0)
expire(key, time);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根據(jù)索引修改list中的某條數(shù)據(jù)
*
* @param key 鍵
* @param index 索引
* @param value 值
* @return
*/
public boolean lUpdateIndex(String key, long index, Object value) {
try {
redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 移除N個(gè)值為value
*
* @param key 鍵
* @param count 移除多少個(gè)
* @param value 值
* @return 移除的個(gè)數(shù)
*/
public long lRemove(String key, long count, Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, count, value);
return remove;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/****************** List end ****************/
}測試
登陸
使用一個(gè)權(quán)限值為20的賬號登陸

執(zhí)行權(quán)限所需20以上的查詢用戶操作
獲取到數(shù)據(jù)

執(zhí)行權(quán)限所需100以上的刪除用戶操作
可見提示權(quán)限不足

到此這篇關(guān)于SpringBoot切面實(shí)現(xiàn)token權(quán)限校驗(yàn)詳解的文章就介紹到這了,更多相關(guān)SpringBoot實(shí)現(xiàn)token權(quán)限內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java基礎(chǔ)之finally語句與return語句詳解
這篇文章主要介紹了Java基礎(chǔ)之finally語句與return語句詳解,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-04-04
Java中的volatile關(guān)鍵字經(jīng)典應(yīng)用場景和常見問題
這篇文章主要介紹了Java中volatile關(guān)鍵字經(jīng)典應(yīng)用場景和常見問題的相關(guān)資料,volatile是一種輕量級鎖的實(shí)現(xiàn),它針對的僅僅是共享變量,不會對線程加鎖,更不會造成線程的阻塞,需要的朋友可以參考下2026-03-03
Java多線程程序中synchronized修飾方法的使用實(shí)例
synchronized關(guān)鍵字主要北用來進(jìn)行線程同步,這里我們主要來演示Java多線程程序中synchronized修飾方法的使用實(shí)例,需要的朋友可以參考下:2016-06-06
基于FLink實(shí)現(xiàn)實(shí)時(shí)安全檢測的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何基于FLink實(shí)現(xiàn)實(shí)時(shí)安全檢測的功能,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的可以了解一下2023-02-02
Java 注解@AliasFor使用方式及實(shí)際案例
本文將全面介紹@AliasFor注解的使用方式、應(yīng)用場景、源碼解析以及實(shí)際案例,幫助你徹底掌握這個(gè)高級注解,感興趣的朋友一起看看吧2025-08-08
解決springboot的aop切面不起作用問題(失效的排查)
這篇文章主要介紹了解決springboot的aop切面不起作用問題(失效的排查),具有很好的參考價(jià)值,希望對大家有所幫助。 一起跟隨小編過來看看吧2020-04-04
SpringBoot返回Json對象報(bào)錯(cuò)(返回對象為空{(diào)})
本文主要介紹介紹了SpringBoot返回Json對象報(bào)錯(cuò)(返回對象為空{(diào)}),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01

