springboot集成sa-token来实现登录鉴权(一)

springboot集成sa-token来实现登录鉴权(一)

  • springboot集成sa-token来实现登录鉴权(一)
    • sa-token简介
    • spirngboot集成sa-token代码实现
      • maven依赖
      • 配置文件
      • 全局异常处理
      • 登录相关接口
        • controller层
        • service层
        • 接口中的参数类
        • 返回数据封装
        • 全局变量类和枚举类
        • 验证码图片工具类
        • redis工具类
    • 测试演示
      • 首先获取一个临时token
      • 然后获取验证码图片
      • 其次是真正的登录接口调用
      • 其他接口,调用的时候会校验是否登录

springboot集成sa-token来实现登录鉴权(一)

这篇文章,我们将学习怎样初步集成sa-token来实现基本的登录认证和权限校验,并初步看下底层的源码实现。

sa-token简介

sa-token是一个轻量级的登录鉴权框架,比之前的shiro和springsecurity都要轻量,一行代码就可以实现登录功能。具体文档可以看:sa-token官网。这里我们不再赘述。直接来看具体实现代码。

spirngboot集成sa-token代码实现

点击看项目源码

maven依赖

		
        <dependency>
            <groupId>cn.dev33groupId>
            <artifactId>sa-token-spring-boot-starterartifactId>
            <version>1.34.0version>
        dependency>

        
        <dependency>
            <groupId>cn.dev33groupId>
            <artifactId>sa-token-dao-redis-jacksonartifactId>
            <version>1.34.0version>
        dependency>

        
        <dependency>
            <groupId>org.apache.commonsgroupId>
            <artifactId>commons-pool2artifactId>
        dependency>

其中,如果是springboot3.x版本的话,上面的sa-token-spring-boot-starter依赖要换成sa-token-spring-boot3-starter

配置文件

@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SaInterceptor(handler -> {
            SaRouter.match("/**", StpUtil::checkLogin)
                    .notMatch(SaTokenConstant.excludePathPatterns);
            // 这里可以给每个接口地址的路径鉴权,当然,也可以用注解在每个接口上鉴权
        })).addPathPatterns(SaTokenConstant.allRouters)
                .excludePathPatterns(SaTokenConstant.excludePathPatterns);
    }

    @Bean
    @Primary
    public SaTokenConfig getSaTokenConfigPrimary(){
        SaTokenConfig config = new SaTokenConfig();
        // token名称
        config.setTokenName(SaTokenConstant.TOKEN_NAME);
        // token有效期,单位 秒,默认是30天
        config.setTimeout(30 * 24 * 60 * 60);
        // token无操作存活时间(指定时间内无操作就视为token过期) 单位:秒
        config.setActivityTimeout(SaTokenConstant.ACTIVITY_TIMEOUT);
        // 是否允许同一账号并发登录,true是允许多个同一账号一起登录,false时同一账号新登录的会挤掉旧登录的
        config.setIsConcurrent(false);
        // 在多人登录同一账号时,是否共用一个token
        config.setIsShare(true);
        // token风格
        config.setTokenStyle(TokenStyleEnum.SIMPLE_UUID.getTokenStyle());
        // 是否输出操作日志
        config.setIsLog(false);
        /*
         是否尝试从 cookie 里读取 Token,此值为 false 后,StpUtil.login(id) 登录时也不会再往前端注入Cookie,
         false时,可以返回给前端token,然后让前端在每次请求时header里携带返回的token,
         这样可以用于不能使用cookie的设备端,不在局限于web浏览器端
         */
        config.setIsReadCookie(false);
        return config;
    }
}

全局异常处理

/**
 * 全局异常处理
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 全局登录异常处理
     * @param exception 登录抛出的异常
     * @return 提示信息
     */
    @ExceptionHandler(NotLoginException.class)
    public BaseResult<Object> handlerNotLoginException(NotLoginException exception) {
        // 打印日志
        log.error(exception.getMessage(), exception);
        // 判断登录异常的场景,定制化返回提示
        String type = exception.getType();
        switch (type){
            case NotLoginException.INVALID_TOKEN:
            case NotLoginException.TOKEN_TIMEOUT:
                return BaseResult.fail(520, SaTokenConstant.TOKEN_OVERDUE);
            case NotLoginException.BE_REPLACED:
            case NotLoginException.KICK_OUT:
                return BaseResult.fail(520, SaTokenConstant.LOGIN_REPLACE);
            default:
                return BaseResult.fail(520, SaTokenConstant.NOT_TOKEN);
        }
    }

    /**
     * 全局权限校验异常处理
     * @param exception 权限校验异常
     * @return
     */
    @ExceptionHandler(NotPermissionException.class)
    public BaseResult<String> handlerNotPermissionException(NotPermissionException exception){
        // 打印日志
        log.error(exception.getMessage(), exception);
        return BaseResult.fail(520, SaTokenConstant.PERMISSION_ERROR);
    }
}

登录相关接口

这里我们模拟下真实的登录场景:
用户在登录页一般会看到三个输入框,分别是:账号、密码和验证码图片。那么我们首先要在登录页面获取到验证码图片,并在登录接口中传入验证码并进行校验,那么后端就必须要存下返回给前端的验证码,那么我们需要先返回前端一个临时token,然后前端拿着这个临时token来请求获取验证码的接口,后端拿到这个临时token后,生成验证码,并将这个临时token作为缓存的key,验证码内容作为value存入缓存中。等到前端调用真正的登录接口时,需要传入 账号、密码、验证码和临时token,在这个接口中,我们通过临时token,去缓存中拿到验证码,和前端传入的验证码进行比对,然后再校验账号和密码。

controller层

@RestController
@Slf4j
public class LoginController {

    @Resource
    private VerifyImgUtil verifyImgUtil;

    @Resource
    private LoginService loginService;

    /**
     * 在获取验证码接口和登录接口前,先调用,获取一个临时token,用来作为验证码的key
     *
     * @return
     */
    @GetMapping("tempToken")
    public BaseResult<String> getTempToken(@RequestParam("tokenKey") String tokenKey) {
        log.info("开始获取临时token------>" + tokenKey);
        String token = SaTempUtil.createToken(tokenKey, 5 * 60);
        loginService.saveTempToken(token);
        return BaseResult.success(token, null);
    }

    /**
     * 获取图片验证码
     *
     * @param tempToken 获取到的临时token
     * @param response
     */
    @GetMapping("getVerifyImg")
    public BaseResult<String> getVerifyImg(@RequestParam("tempToken") String tempToken, HttpServletResponse response) throws IOException {
        log.info("开始获取图片验证码------>" + tempToken);
        if (!loginService.checkTempToken(tempToken)) {
            return BaseResult.fail(530, LoginConstant.TOKEN_EMPTY);
        }
        response.setContentType("image/jpeg");//设置相应类型,告诉浏览器输出的内容为图片
        response.setHeader("Pragma", "No-cache");//设置响应头信息,告诉浏览器不要缓存此内容
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        OutputStream os = response.getOutputStream();
        verifyImgUtil.lineCaptcha(os, tempToken);
        try {
            os.flush();
        } finally {
            os.close();
        }
        return null;
    }

    /**
     * 模拟登录接口,真实场景中,可以先提供一个接口,返回一个临时token,
     * 然后再提供一个获取验证码的接口,里面需要传入刚才返回的临时token,生成验证码后,以临时token作为key,验证码作为value放入缓存,
     * 然后再来调用这个正式登录接口,里面需要传验证码和临时token以及用户的账号密码,先根据临时token从缓存中获取验证码来比对,
     * 然后再比对账号密码,比对成功后,删除缓存中对应临时token的验证码数据,并删除临时token
     *
     * @param dto 登录数据
     * @return
     */
    @PostMapping("/login")
    public BaseResult<String> login(@RequestBody LoginDto dto) {
        log.info("开始登录------>" + JSON.toJSONString(dto));
        BaseResult<String> result = loginService.checkLogin(dto);
        if (!result.isState()) {
            return result;
        }
        loginService.deleteTempToken(dto.getTempToken());// 校验成功后移除临时token
        // 登录
        StpUtil.login("10001");
        // 将用户的数据放入上下文session中
        StpUtil.getSession().set(LoginConstant.LOGIN_NAME, "admin");
        StpUtil.getSession().set(LoginConstant.REAL_NAME, "管理员");
        StpUtil.getSession().set(LoginConstant.USER_ID, "10001");
        return BaseResult.success(StpUtil.getTokenValue(), "登录成功");
    }

    /**
     * 注销登录接口
     */
    @PostMapping("logout")
    public void logout(){
        StpUtil.logout();
    }
}

service层

public interface LoginService {

    /**
     * 登录校验
     * @param dto
     * @return
     */
    BaseResult<String> checkLogin(LoginDto dto);

    /**
     * 存放临时token
     * @param tempToken 临时token
     */
    void saveTempToken(String tempToken);

    /**
     * 删除临时token
     * @param tempToken 临时token
     */
    void deleteTempToken(String tempToken);

    /**
     * 校验临时token是否有效
     * @param tempToken 临时token
     * @return
     */
    boolean checkTempToken(String tempToken);
}
@Service
public class LoginServiceImpl implements LoginService {

    @Resource
    private RedisUtil redisUtil;

    private static final String tempTokenPre = "tempToken";

    @Override
    public BaseResult<String> checkLogin(LoginDto dto) {
        if (StringUtils.isBlank(dto.getTempToken())) {
            return BaseResult.fail(530, LoginConstant.TOKEN_EMPTY);
        }
        if (StringUtils.isBlank(dto.getVerifyCode())) {
            return BaseResult.fail(530, LoginConstant.VERIFY_CODE_EMPTY);
        }
        if (StringUtils.isBlank(dto.getLoginName())) {
            return BaseResult.fail(530, LoginConstant.LOGIN_NAME_EMPTY);
        }
        if (StringUtils.isBlank(dto.getPassword())) {
            return BaseResult.fail(530, LoginConstant.PASSWORD_EMPTY);
        }
        // 校验
        Object verifyCode = redisUtil.get(dto.getTempToken());
        if (verifyCode == null) {
            return BaseResult.fail(530, LoginConstant.VERIFY_OVERDUE);
        }
        if (!dto.getVerifyCode().equalsIgnoreCase(verifyCode.toString())) {
            return BaseResult.fail(530, LoginConstant.VERIFY_CODE_ERROR);
        }
        if (!"admin".equals(dto.getLoginName())) {
            return BaseResult.fail(530, LoginConstant.LOGIN_NAME_ERROR);
        }
        if (!"123".equals(dto.getPassword())) {
            return BaseResult.fail(530, LoginConstant.PASSWORD_ERROR);
        }
        // 校验成功后,移除redis
        redisUtil.delete(dto.getTempToken());
        return BaseResult.success(null, null);
    }

    @Override
    public void saveTempToken(String tempToken) {
        redisUtil.set(tempTokenPre + tempToken, "1", 300);
    }

    @Override
    public void deleteTempToken(String tempToken) {
        redisUtil.delete(tempTokenPre + tempToken);
    }

    @Override
    public boolean checkTempToken(String tempToken) {
        Object o = redisUtil.get(tempTokenPre + tempToken);
        return o != null;
    }
}

接口中的参数类

@Data
public class LoginDto implements Serializable {

    /**
     * 账号
     */
    private String loginName;

    /**
     * 密码
     */
    private String password;

    /**
     * 验证码
     */
    private String verifyCode;

    /**
     * 临时token,用来校验验证码
     */
    private String tempToken;
}

返回数据封装

@Data
public class BaseResult<T> implements Serializable {

    /**
     * 返回数据
     */
    private T data;

    /**
     * 提示信息
     */
    private String message;

    /**
     * 状态码
     */
    private int code;

    /**
     * 状态
     */
    private boolean state = true;

    public static <T> BaseResult<T> result(int code, String message, boolean state) {
        BaseResult<T> result = new BaseResult<>();
        result.setCode(code);
        result.setMessage(message);
        result.setState(state);
        return result;
    }

    /**
     * 返回信息
     *
     * @param code    状态码
     * @param message 信息
     * @param t       数据
     * @param      T
     * @return ResultVo
     */
    public static <T> BaseResult<T> result(int code, String message, T t, boolean state) {
        BaseResult<T> r = new BaseResult<>();
        r.setCode(code);
        r.setMessage(message);
        r.setData(t);
        r.setState(state);
        return r;
    }

    /**
     * 返回成功
     *
     * @param data data
     * @param   T
     * @return ResultVo
     */
    public static <T> BaseResult<T> success(T data, String message) {
        return result(HttpStatus.OK.value(), message, data, true);
    }

    /**
     * 返回失败
     *
     * @param code code
     * @param   T
     * @return ResultVo
     */
    public static <T> BaseResult<T> fail(int code, String message) {
        return result(code, message, null, false);
    }
}

全局变量类和枚举类

/**
 * 要排除登录校验的接口地址枚举类
 */
@Getter
public enum ExcludePathEnum {
    TEMP_TOKEN("/tempToken", "获取临时token的接口"),
    VERIFY_IMG("/getVerifyImg", "获取验证码图片的接口"),
    LOGIN("/login", "登录接口"),
    LOGOUT("/logout", "注销登录接口");

    private final String path;
    private final String remark;

    ExcludePathEnum(String path, String remark) {
        this.path = path;
        this.remark = remark;
    }
}
public class LoginConstant {
    public static final String TOKEN_EMPTY = "token不能为空!";
    public static final String LOGIN_NAME_EMPTY = "请输入账号!";
    public static final String PASSWORD_EMPTY = "请输入密码!";
    public static final String LOGIN_NAME_ERROR = "账号不存在!";
    public static final String PASSWORD_ERROR = "密码错误,请重新输入!";
    public static final String VERIFY_CODE_EMPTY = "验证码不能为空!";
    public static final String VERIFY_CODE_ERROR = "验证码错误,请重新输入!";
    public static final String VERIFY_OVERDUE = "验证码已过期,请重新登录!";

    public static final String LOGIN_NAME = "loginName";
    public static final String REAL_NAME = "userName";
    public static final String USER_ID = "userId";
}
public class SaTokenConstant {

    /**
     * token的字段名
     */
    public static final String TOKEN_NAME = "token";

    /**
     * token无操作存活时间(指定时间内无操作就视为token过期) 单位:秒
     */
    public static final long ACTIVITY_TIMEOUT = 24 * 60 * 60;

    public static final List<String> allRouters = Collections.singletonList("/**");

    public static final List<String> excludePathPatterns = Arrays.asList(
            "/test/**",
            "/file/upload/img/head/**",
            "/swagger-resources/**",
            "/webjars/**",
            "/v2/**",
            "/doc.html",
            "**/swagger-ui.html",
            "/swagger-ui.html/**",
            "/img/head/**",
            ExcludePathEnum.TEMP_TOKEN.getPath(),
            ExcludePathEnum.VERIFY_IMG.getPath(),
            ExcludePathEnum.LOGIN.getPath(),
            ExcludePathEnum.LOGOUT.getPath()
    );

    public static final String NOT_TOKEN = "您未登录,请登录!";

    public static final String TOKEN_OVERDUE = "登录已失效,请重新登录!";

    public static final String LOGIN_REPLACE = "您的账号已在别处登录!";

    public static final String PERMISSION_ERROR = "您没有权限!";
}
@Getter
public enum TokenStyleEnum {
    /**
     * 一般的uuid风格
     */
    UUID("uuid"),
    /**
     * uuid风格,只不过去掉了中划线
     */
    SIMPLE_UUID("simple-uuid"),
    /**
     * 随机32位字符串
     */
    RANDOM_32("random-32"),
    /**
     * 随机64位字符串
     */
    RANDOM_64("random-64"),
    /**
     * 随机128位字符串
     */
    RANDOM_128("random-128"),
    /**
     * tik风格,gr_SwoIN0MC1ewxHX_vfCW3BothWDZMMtx__
     */
    TIK("tik");

    private final String tokenStyle;

    TokenStyleEnum(String tokenStyle) {
        this.tokenStyle = tokenStyle;
    }
}

验证码图片工具类

这里的验证码图片生成用的是hultool包的工具类,需要先导入hultool包
maven:

		<dependency>
            <groupId>cn.hutoolgroupId>
            <artifactId>hutool-allartifactId>
            <version>5.8.15version>
        dependency>

封装的工具类:

@Component
public class VerifyImgUtil {

    @Resource
    private RedisUtil redisUtil;

    /**
     * 生成验证码的字符,去掉了0、1、I、O这样容易混淆的字符
     */
    public static final String VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";

    /**
     * 生成线段干扰的验证码
     *
     * @param os        输出流
     * @param tempToken 临时token,作为验证码写入缓存的key
     */
    public void lineCaptcha(OutputStream os, String tempToken) {
        //定义图形验证码的长和宽
        LineCaptcha captcha = CaptchaUtil.createLineCaptcha(200, 100);
        // 自定义纯数字的验证码(随机4位字符,可重复)
        RandomGenerator randomGenerator = new RandomGenerator(VERIFY_CODES, 4);
        captcha.setGenerator(randomGenerator);
        putVerifyCode(tempToken, captcha.getCode());
        captcha.write(os);
    }

    /**
     * 生成圆圈干扰的验证码
     *
     * @param os        输出流
     * @param tempToken 临时token,作为验证码写入缓存的key
     */
    public void circleCaptcha(OutputStream os, String tempToken) {
        //定义图形验证码的长、宽、验证码字符数、干扰元素个数
        CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(200, 100, 4, 20);
        // 自定义纯数字的验证码(随机4位字符,可重复)
        RandomGenerator randomGenerator = new RandomGenerator(VERIFY_CODES, 4);
        captcha.setGenerator(randomGenerator);
        putVerifyCode(tempToken, captcha.getCode());
        captcha.write(os);
    }

    /**
     * 生成扭曲干扰的验证码
     *
     * @param os        输出流
     * @param tempToken 临时token,作为验证码写入缓存的key
     */
    public void shearCaptcha(OutputStream os, String tempToken) {
        //定义图形验证码的长、宽、验证码字符数、干扰线宽度
        ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(200, 100, 4, 4);
        // 自定义纯数字的验证码(随机4位字符,可重复)
        RandomGenerator randomGenerator = new RandomGenerator(VERIFY_CODES, 4);
        captcha.setGenerator(randomGenerator);
        putVerifyCode(tempToken, captcha.getCode());
        captcha.write(os);
    }

    /**
     * 将验证码放到缓存里
     *
     * @param tempToken  临时token,作为验证码写入缓存的key
     * @param verifyCode 验证码
     */
    private void putVerifyCode(String tempToken, String verifyCode) {
        redisUtil.set(tempToken, verifyCode, 40);
    }
}

redis工具类

@Component
public class RedisUtil {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 获取符合要求的所有key
     * @param patternKey 指定要求的key
     * @return 获取符合要求的所有key集合
     */
    public Set<String> getAllKey(String patternKey){
        return redisTemplate.keys(patternKey);
    }

    /**
     * 清空所有的redis数据库
     */
    public void flushAll(){
        redisTemplate.getConnectionFactory().getConnection().flushAll();
    }

    /**
     * 清空当前数据库
     */
    public void flushDB(){
        redisTemplate.getConnectionFactory().getConnection().flushDb();
    }

    /**
     * 指定缓存的有效期
     * @param key 缓存key
     * @param time 有效时间,已秒为单位
     * @return
     */
    public Boolean expire(String key, long time){
        if (time > 0){
            return redisTemplate.expire(key, time, TimeUnit.SECONDS);
        }
        return true;
    }

    /**
     * 获取指定key的过期时间,返回0表示永久有效
     * @param key 缓存key
     * @return 过期时间
     */
    public Long getExpire(String key){
        return redisTemplate.getExpire(key);
    }

    /**
     * 判断指定的缓存key是否存在
     * @param key 缓存key
     * @return
     */
    public Boolean hasKey(String key){
        return redisTemplate.hasKey(key);
    }

    /**
     * 删除指定的key,可以传入一个String数组,批量删除
     * @param key 缓存key数组
     */
    public void delete(String... key){
        if (key == null || key.length < 1){
            return;
        }
        if (key.length == 1){
            redisTemplate.delete(key[0]);
        } else {
            redisTemplate.delete(Arrays.asList(key));
        }
    }

    /**
     * String类型的添加缓存数据
     * @param key 缓存key
     * @param value 缓存value
     */
    public void set(String key, Object value){
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * String类型的添加缓存数据,并设置过期时间,单位为秒
     * @param key 缓存key
     * @param value 缓存value
     * @param time 过期时间
     */
    public void set(String key, Object value, long time){
        redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
    }

    /**
     * 获取指定key的缓存数据
     * @param key 缓存key
     * @return
     */
    public Object get(String key){
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * 指定key的值递增
     * @param key 缓存key
     * @param delta 递增因子,即每次递增加几
     * @return
     */
    public Long incr(String key, long delta){
        if (delta < 0){
            throw new RuntimeException("递增因子要大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 指定key的值递减
     * @param key 缓存key
     * @param delta 递减因子,即每次递减减几
     * @return
     */
    public Long decr(String key, long delta){
        if (delta < 0){
            throw new RuntimeException("递减因子要大于0");
        }
        return redisTemplate.opsForValue().decrement(key, delta);
    }

    /**
     * 

Hash类型

* 获取指定key的指定键值对的值 * @param key 缓存key * @param hashKey hash类型的键值对的key * @return */
public Object hget(String key, String hashKey){ return redisTemplate.opsForHash().get(key, hashKey); } /** *

Hash类型

* 获取指定key的所有键值对的值 * @param key 缓存key * @return */
public Map<Object, Object> hmget(String key){ return redisTemplate.opsForHash().entries(key); } /** *

Hash类型

* 添加指定缓存key的多个键值对 * @param key 缓存key * @param map 对应的多个键值对 */
public void hmset(String key, Map<Object, Object> map){ redisTemplate.opsForHash().putAll(key, map); } /** *

Hash类型

* 添加指定缓存key的多个键值对,并设置过期时间,以秒为单位 * @param key 缓存key * @param map 对应的多个键值对 * @param time 过期时间 */
public void hmset(String key, Map<Object, Object> map, long time){ redisTemplate.opsForHash().putAll(key, map); expire(key, time); } /** *

Hash类型

* 添加指定缓存key的一个键值对 * @param key 换存key * @param hashKey 对应的键值对的key * @param value 对应的键值对的value */
public void hSet(String key, String hashKey, Object value){ redisTemplate.opsForHash().put(key, hashKey, value); } /** *

Hash类型

* 添加指定缓存key的一个键值对,并设置过期时间,以秒为单位 * @param key 缓存key * @param hashKey 对应的键值对的key * @param value 对应的键值对的value * @param time 过期时间 */
public void hSet(String key, String hashKey, Object value, long time){ hSet(key, hashKey, value); expire(key, time); } /** *

Hash类型

* 删除指定key的指定键值对 * @param key 缓存key * @param hashKey 要删除的键值对的key */
public void hDelete(String key, Object... hashKey){ redisTemplate.opsForHash().delete(key, hashKey); } /** *

Hash类型

* 判断缓存中是否有指定key的指定键值对 * @param key 缓存key * @param hashKey 对应键值对的key * @return */
public Boolean hHashKey(String key, Object hashKey){ return redisTemplate.opsForHash().hasKey(key, hashKey); } /** *

Hash类型

* 递增指定key的指定键值对的值,如果不存在,则会创建,并且返回新增后的值 * @param key 缓存key * @param hashKey 指定键值对的key * @param delta 递增因子,即要加几 * @return */
public double hIncr(String key, String hashKey, long delta) { return redisTemplate.opsForHash().increment(key, hashKey, delta); } /** *

Hash类型

* 递减指定key的指定键值对的值,如果不存在,则会创建,并且返回新增后的值 * @param key 缓存key * @param hashKey 指定键值对的key * @param delta 递减因子,即要减几 * @return */
public double hDecr(String key, String hashKey, long delta) { return redisTemplate.opsForHash().increment(key, hashKey, -delta); } //================================Set=========================== /** *

Set类型

* 根据key获取Set中的所有值 * @param key 缓存key * @return */
public Set<Object> sGet(String key) { return redisTemplate.opsForSet().members(key); } /** *

Set类型

* 查询指定的key中指定的value是否存在 * @param key 缓存key * @param value Set中的指定元素 * @return */
public Boolean sHasKey(String key, Object value) { return redisTemplate.opsForSet().isMember(key, value); } /** *

Set类型

* 将缓存数据放入指定的key中 * @param key 缓存key * @param values Set集合 * @return */
public Long sSet(String key, Object... values) { return redisTemplate.opsForSet().add(key, values); } /** *

Set类型

* 将缓存数据放入指定的key中,并设置过期时间,单位为秒 * @param key 缓存key * @param time 过期时间 * @param values 要放入缓存的数据 * @return */
public Long sSet(String key, long time, Object... values) { Long l = sSet(key, values); expire(key, time); return l; } /** *

Set类型

* 获取指定的key中Set的长度 * @param key 缓存key * @return */
public Long sGetSetLength(String key) { Long l = redisTemplate.opsForSet().size(key); return l == null ? 0 : l; } /** *

Set类型

* 移除指定的key中指定的value * @param key 缓存key * @param values 指定要移除的value * @return */
public long sRemove(String key, Object... values) { Long l = redisTemplate.opsForSet().remove(key, values); return l == null ? 0 : l; } //==========================List======================= /** *

List类型

* 获取指定的key中的list集合内容,根据起始下标获取 * @param key 缓存key * @param start 集合的开始下标,包含在内 * @param end 集合的截止下标,也包含在内 * @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类型

* 根据key获取list集合的长度 * @param key 缓存key * @return */
public long lGetLength(String key) { Long l = redisTemplate.opsForList().size(key); return l == null ? 0 : l; } /** *

List类型

* 获取指定key的指定下标的元素 * @param key 缓存key * @param index 指定的list集合下标 * @return */
public Object lGetByIndex(String key, long index) { try { return redisTemplate.opsForList().index(key, index); } catch (Exception e) { e.printStackTrace(); return null; } } /** *

List类型

* 将值从左侧放入List类型的缓存中,头插法 * @param key 缓存key * @param value 要放入缓存的值 * @return */
public void lSet(String key, Object value) { redisTemplate.opsForList().leftPush(key, value); } /** *

List类型

* 将值从右侧放入List类型的缓存中,尾插法 * @param key 缓存key * @param value 要放入缓存的值 */
public void rSet(String key, Object value) { redisTemplate.opsForList().rightPush(key, value); } /** *

List类型

* 将值从左侧放入List类型的缓存中,头插法,并设置过期时间,单位为秒 * @param key 缓存key * @param value 要放入缓存的值 * @param time 过期时间 * @return */
public void lSet(String key, Object value, long time) { redisTemplate.opsForList().leftPush(key, value); expire(key, time); } /** *

List类型

* 将值从右侧放入List类型的缓存中,尾插法,并设置过期时间,单位为秒 * @param key 缓存key * @param value 要放入缓存的值 * @param time 过期时间 */
public void rSet(String key, Object value, long time) { redisTemplate.opsForList().rightPush(key, value); expire(key, time); } /** *

List类型

* 将list集合从左边放入缓存,头插法 * @param key 缓存key * @param list 要放入缓存的集合 */
public void lSet(String key, List<Object> list) { redisTemplate.opsForList().leftPushAll(key, list); } /** *

List类型

* 将list集合从右边放入缓存,尾插法 * @param key 缓存key * @param list 要放入缓存的集合 */
public void rSet(String key, List<Object> list) { redisTemplate.opsForList().rightPushAll(key, list); } /** *

List类型

* 将list集合从左边放入缓存,头插法,并设置过期时间,单位为秒 * @param key 缓存key * @param list 要放入缓存的集合 * @param time 过期时间 */
public void lSet(String key, List<Object> list, long time) { redisTemplate.opsForList().leftPushAll(key, list); expire(key, time); } /** *

List类型

* 将list集合从右边放入缓存,尾插法,并设置过期时间,单位为秒 * @param key 缓存key * @param list 要放入缓存的集合 * @param time 过期时间 */
public void rSet(String key, List<Object> list, long time) { redisTemplate.opsForList().rightPushAll(key, list); expire(key, time); } /** *

List类型

* 修改指定key的list集合中指定下标的值 * @param key 缓存key * @param index 要修改的值的下标 * @param value 修改的值 */
public void lUpdateIndex(String key, long index, Object value) { redisTemplate.opsForList().set(key, index, value); } /** *

List类型

*

移除指定key的list集合中指定个数的指定值

*

若count = 0,则表示移除全部

*

若count > 0,则表示从List集合的左侧开始数

*

若count < 0,则表示从List集合的右侧开始数

* @param key 缓存key * @param count 要移除的元素个数 * @param value 要移除的值 * @return */
public Long lRemove(String key, long count, Object value) { Long l = redisTemplate.opsForList().remove(key, count, value); return l == null ? 0L : l; } //===============================ZSet============================= /** *

ZSet类型

* 添加ZSet类型的缓存,这是一个有序集合,是按照元素的scores的值由小到大排序的 * @param key 缓存key * @param value 要添加的值 * @param scores 值的scores,根据此值的大小来排序 */
public void zAdd(String key, String value, double scores) { redisTemplate.opsForZSet().add(key, value, scores); } /** *

ZSet类型

* 批量添加ZSet类型的缓存,将一个set集合添加的ZSet中 * @param key 缓存key * @param values 要放入缓存的set集合 */
public void zAdd(String key, Set<ZSetOperations.TypedTuple<Object>> values) { redisTemplate.opsForZSet().add(key, values); } /** *

ZSet类型

* 移除指定key中ZSet集合中的一个或多个指定的元素 * @param key 缓存key * @param values 要移除的元素 * @return */
public Long zRemove(String key, Object... values) { Long l = redisTemplate.opsForZSet().remove(key, values); return l == null ? 0L : l; } /** *

ZSet类型

* 增加指定key的ZSet集合中指定元素的scores,并返回增加后的scores值 * @param key 缓存key * @param value 要增加scores的元素 * @param delta 递增因子,即加几 * @return 增加后的scores值 */
public Double zincr(String key, String value, double delta) { return redisTemplate.opsForZSet().incrementScore(key, value, delta); } /** *

ZSet类型

* 返回指定key中ZSet集合中指定元素的下标 * @param key 缓存key * @param value 要获取下标的元素 * @return 指定元素的下标 */
public Long zRank(String key, Object value) { return redisTemplate.opsForZSet().rank(key, value); } /** *

ZSet类型

* 获取指定key的ZSet集合中指定下标区间的元素,由小到大排序 * @param key 缓存key * @param start 开始下标,包含在内 * @param end 截止下标,也包含在内 * @return 指定下标区间内的元素 */
public Set<Object> zRange(String key, long start, long end) { return redisTemplate.opsForZSet().range(key, start, end); } /** *

ZSet类型

* 获取指定key的ZSet集合中指定下标区间的元素,由大到小排序 * @param key 缓存key * @param start 开始下标,包含在内 * @param end 截止下标,也包含在内 * @return 指定下标区间内的元素 */
public Set<Object> zReRange(String key, long start, long end) { return redisTemplate.opsForZSet().reverseRange(key, start, end); } /** *

ZSet类型

* 获取指定key的ZSet集合中指定下标区间的元素,并带上元素的scores * @param key 缓存key * @param start 开始下标,包含在内 * @param end 截止下标,也包含在内 * @return 指定下标区间内的元素 */
public Set<ZSetOperations.TypedTuple<Object>> zRangeWithScores(String key, long start, long end) { return redisTemplate.opsForZSet().rangeWithScores(key, start, end); } /** *

ZSet类型

* 获取指定key的ZSet集合中指定scores的元素 * @param key 缓存key * @param scores 值的scores,根据此值的大小来排序 * @return */
public Object zScores(String key, double scores) { return redisTemplate.opsForZSet().score(key, scores); } }

测试演示

首先获取一个临时token

springboot集成sa-token来实现登录鉴权(一)_第1张图片

然后获取验证码图片

springboot集成sa-token来实现登录鉴权(一)_第2张图片

其次是真正的登录接口调用

springboot集成sa-token来实现登录鉴权(一)_第3张图片
这里获取到真正的token后,前端就要在之后的接口中将这个token放入header中,至于这个header的字段名叫什么,在springboot集成sa-token来实现登录鉴权(一)_第4张图片
这里的配置文件中会配置,配置后,接口的登录校验就会从header中获取这个字段的值来进行登录校验

其他接口,调用的时候会校验是否登录

已经登录后的调用返回:
springboot集成sa-token来实现登录鉴权(一)_第5张图片
未登录的调用返回:
springboot集成sa-token来实现登录鉴权(一)_第6张图片

你可能感兴趣的:(sa-token,spring,boot,java,sa-token,登录,spring)