我的编程空间,编程开发者的网络收藏夹
学习永远不晚

springboot整合sa-token简介及入门教程

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

springboot整合sa-token简介及入门教程

springboot:整合sa-token

一、简介

Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证权限认证Session会话单点登录OAuth2.0微服务网关鉴权 等一系列权限相关问题

Sa-token官方文档

二、入门程序

1.添加依赖

<!-- Sa-Token 权限认证, 在线文档:http://sa-token.dev33.cn/ -->
		<dependency>
    		<groupId>cn.dev33</groupId>
    		<artifactId>sa-token-spring-boot-starter</artifactId>
    		<version>1.29.1.trial</version>
		</dependency>
         <dependency>
             <groupId>cn.hutool</groupId>
             <artifactId>hutool-all</artifactId>
             <version>5.6.3</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.29</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
        </dependency>

2.sa-token配置类

@Configuration
public class SaTokenConfiguration {
    private static final String TOKEN_NAME = "sa-token";
    private static final Integer TIMEOUT = 2592000;
    private static final Integer ACTIVITY_TIMEOUT = -1;
    private static final String TOKEN_STYLE = "uuid";
    @Bean
    public SaTokenConfig saTokenConfig(){
        SaTokenConfig saTokenConfig = new SaTokenConfig();
        // token名称 (同时也是cookie名称)
        saTokenConfig.setTokenName(TOKEN_NAME);
        // token有效期,单位s 默认30天, -1代表永不过期
        saTokenConfig.setTimeout(TIMEOUT);
        // token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
        saTokenConfig.setActivityTimeout(ACTIVITY_TIMEOUT);
        // 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
        saTokenConfig.setAllowConcurrentLogin(true);
        // 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
        saTokenConfig.setIsShare(true);
        // token风格
        saTokenConfig.setTokenStyle(TOKEN_STYLE);
        return saTokenConfig;
    }
}

3.测试controller

@RestController
@RequestMapping("/user/")
public class UserController {
    // 测试登录,浏览器访问: http://localhost:8081/user/doLogin?username=zhang&password=123456
    @RequestMapping("doLogin")
    public String doLogin(String username, String password) {
        // 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对 
        if("zhang".equals(username) && "123456".equals(password)) {
            StpUtil.login(10001);
            return "登录成功";
        }
        return "登录失败";
    }
    // 查询登录状态,浏览器访问: http://localhost:8081/user/isLogin
    @RequestMapping("isLogin")
    public String isLogin() {
        return "当前会话是否登录:" + StpUtil.isLogin();
    }
}

三、认证登录

1.mysql配置类

@Configuration
@EnableTransactionManagement
@MapperScan(basePackages = {"com.yolo.springbootsatoken.mapper"}, sqlSessionFactoryRef = "domeSqlSessionFactory")
public class MysqlConfiguration {
    @Bean(name = "domeDataSource")
    @Primary
    public DataSource domeDataSource() throws Exception {
        String mysqlHost = mysqlHost = "127.0.0.1";
        String mysqlPort = mysqlPort = "3306";
        String mysqlUsername = mysqlUsername = "root";
        String mysqlPassword =  mysqlPassword = "root";
        String mysqlDB = mysqlDB = "test";
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl("jdbc:mysql://" + mysqlHost + ":" + mysqlPort + "/" + mysqlDB
                + "?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&allowMultiQueries=true");
        dataSource.setPassword(mysqlPassword);
        dataSource.setUsername(mysqlUsername);
        dataSource.setMaxActive(100);
        dataSource.setMaxWait(60000);
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setMinEvictableIdleTimeMillis(300000);
        dataSource.setTimeBetweenEvictionRunsMillis(60000);
        dataSource.setInitialSize(5);
        dataSource.setMinIdle(1);
        return dataSource;
    }
    @Bean(name = "domeTransactionManager")
    @Primary
    public DataSourceTransactionManager domeTransactionManager() throws Exception {
        return new DataSourceTransactionManager(domeDataSource());
    }
    @Bean(name = "domeSqlSessionFactory")
    @Primary
    public SqlSessionFactoryBean sqlSessionFactory(@Qualifier("domeDataSource") DataSource dataSource, PageHelper pageHelper) throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setPlugins(new Interceptor[]{pageHelper});
        return sessionFactory;
    }
    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
    @Bean
    public PageHelper pageHelper() {
        PageHelper pageHelper = new PageHelper();
        Properties p = new Properties();
        p.setProperty("offsetAsPageNum", "true");
        p.setProperty("rowBoundsWithCount", "true");
        p.setProperty("reasonable", "true");
        p.setProperty("dialect", "mysql");
        pageHelper.setProperties(p);
        return pageHelper;
    }
}

2.实体类

@Data
public class User {
    private int id;
    private String username;
    private String realName;
    private String salt;
    private String password;
    private Long createTime;
    private Long updateTime;
    private Long deleteTime;
    private int removed;
}

3.mapper

@Repository
@Mapper
public interface UserMapper {
    @Insert("INSERT INTO user (username,realName,password,salt,createTime,removed) VALUES (" +
            "#{username},#{realName},#{password},#{salt},#{createTime},#{removed})")
    @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
    int createUser(User user);
    @Select("select * from user where username=#{username} and removed=0 ")
    User selectByUsername(@Param("username") String name);
}

4.测试controller

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserMapper userMapper;
    //创建用户  ---- http://localhost:8081/user/create
    @PostMapping("/create")
    public SaResult createUser(@RequestBody User user){
        String md5BySalt = SaSecureUtil.md5BySalt(user.getPassword(), "qwertyuiop");
        user.setSalt("qwertyuiop");
        user.setPassword(md5BySalt);
        user.setCreateTime(System.currentTimeMillis());
        userMapper.createUser(user);
        return SaResult.ok();
    }
    //登录  ---- http://localhost:8081/user/login
    @GetMapping("/login")
    public SaResult doLogin(@RequestParam("username") String name, @RequestParam("password") String pwd) {
        User user = userMapper.selectByUsername(name);
        String password = SaSecureUtil.md5BySalt(pwd, user.getSalt());
        if (password.equals(user.getPassword())){
            StpUtil.login(10001);
            return SaResult.ok("登录成功");
        }
        return SaResult.error("登录失败");
    }
    // 查询登录状态  ---- http://localhost:8081/user/isLogin
    @RequestMapping("isLogin")
    public SaResult isLogin() {
        return SaResult.ok("是否登录:" + StpUtil.isLogin());
    }
    // 查询 Token 信息  ---- http://localhost:8081/user/tokenInfo
    @RequestMapping("tokenInfo")
    public SaResult tokenInfo() {
        return SaResult.data(StpUtil.getTokenInfo());
    }
    // 测试注销  ---- http://localhost:8081/user/logout
    @RequestMapping("logout")
    public SaResult logout() {
        StpUtil.logout();
        return SaResult.ok();
    }
}

四、密码加密

1.摘要加密

// md5加密 
SaSecureUtil.md5("123456");
// sha1加密 
SaSecureUtil.sha1("123456");
// sha256加密 
SaSecureUtil.sha256("123456");
// md5加盐加密: md5(md5(str) + md5(salt)) 
SaSecureUtil.md5BySalt("123456", "salt");

2.对称加密

// 定义秘钥和明文
String key = "123456";
String text = "Sa-Token 一个轻量级java权限认证框架";
// 加密 
String ciphertext = SaSecureUtil.aesEncrypt(key, text);
System.out.println("AES加密后:" + ciphertext);
// 解密 
String text2 = SaSecureUtil.aesDecrypt(key, ciphertext);
System.out.println("AES解密后:" + text2);

3.非对称加密

// 定义私钥和公钥 
String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAO+wmt01pwm9lHMdq7A8gkEigk0XKMfjv+4IjAFhWCSiTeP7dtlnceFJbkWxvbc7Qo3fCOpwmfcskwUc3VSgyiJkNJDs9ivPbvlt8IU2bZ+PBDxYxSCJFrgouVOpAr8ar/b6gNuYTi1vt3FkGtSjACFb002/68RKUTye8/tdcVilAgMBAAECgYA1COmrSqTUJeuD8Su9ChZ0HROhxR8T45PjMmbwIz7ilDsR1+E7R4VOKPZKW4Kz2VvnklMhtJqMs4MwXWunvxAaUFzQTTg2Fu/WU8Y9ha14OaWZABfChMZlpkmpJW9arKmI22ZuxCEsFGxghTiJQ3tK8npj5IZq5vk+6mFHQ6aJAQJBAPghz91Dpuj+0bOUfOUmzi22obWCBncAD/0CqCLnJlpfOoa9bOcXSusGuSPuKy5KiGyblHMgKI6bq7gcM2DWrGUCQQD3SkOcmia2s/6i7DUEzMKaB0bkkX4Ela/xrfV+A3GzTPv9bIBamu0VIHznuiZbeNeyw7sVo4/GTItq/zn2QJdBAkEA8xHsVoyXTVeShaDIWJKTFyT5dJ1TR++/udKIcuiNIap34tZdgGPI+EM1yoTduBM7YWlnGwA9urW0mj7F9e9WIQJAFjxqSfmeg40512KP/ed/lCQVXtYqU7U2BfBTg8pBfhLtEcOg4wTNTroGITwe2NjL5HovJ2n2sqkNXEio6Ji0QQJAFLW1Kt80qypMqot+mHhS+0KfdOpaKeMWMSR4Ij5VfE63WzETEeWAMQESxzhavN1WOTb3/p6icgcVbgPQBaWhGg==";
String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDvsJrdNacJvZRzHauwPIJBIoJNFyjH47/uCIwBYVgkok3j+3bZZ3HhSW5Fsb23O0KN3wjqcJn3LJMFHN1UoMoiZDSQ7PYrz275bfCFNm2fjwQ8WMUgiRa4KLlTqQK/Gq/2+oDbmE4tb7dxZBrUowAhW9NNv+vESlE8nvP7XXFYpQIDAQAB";
// 文本
String text = "Sa-Token 一个轻量级java权限认证框架";
// 使用公钥加密
String ciphertext = SaSecureUtil.rsaEncryptByPublic(publicKey, text);
System.out.println("公钥加密后:" + ciphertext);
// 使用私钥解密
String text2 = SaSecureUtil.rsaDecryptByPrivate(privateKey, ciphertext);
System.out.println("私钥解密后:" + text2); 

// 生成一对公钥和私钥,其中Map对象 (private=私钥, public=公钥) System.out.println(SaSecureUtil.rsaGenerateKeyPair());

4.Base64编码与解码

// 文本
String text = "Sa-Token 一个轻量级java权限认证框架";
// 使用Base64编码
String base64Text = SaBase64Util.encode(text);
System.out.println("Base64编码后:" + base64Text);
// 使用Base64解码
String text2 = SaBase64Util.decode(base64Text);
System.out.println("Base64解码后:" + text2); 

五、权限认证

1.获取当前账号权限码集合


@Component	// 打开此注解,保证此类被springboot扫描,即可完成sa-token的自定义权限验证扩展 
public class StpInterfaceImpl implements StpInterface {
	
	@Override
	public List<String> getPermissionList(Object loginId, String loginKey) {
		// 本list仅做模拟,实际项目中要根据具体业务逻辑来查询权限
		List<String> list = new ArrayList<>();
		list.add("101");
		list.add("user-add");
		list.add("user-delete");
		list.add("user-update");
		list.add("user-get");
		list.add("article-get");
		return list;
	}
	
	@Override
	public List<String> getRoleList(Object loginId, String loginKey) {
		// 本list仅做模拟,实际项目中要根据具体业务逻辑来查询角色
		List<String> list = new ArrayList<>();
		list.add("admin");
		list.add("super-admin");
		return list;
	}
}

2.权限认证

// 判断:当前账号是否含有指定权限, 返回true或false
StpUtil.hasPermission("user-update");        
// 校验:当前账号是否含有指定权限, 如果验证未通过,则抛出异常: NotPermissionException 
StpUtil.checkPermission("user-update");        
// 校验:当前账号是否含有指定权限 [指定多个,必须全部验证通过]
StpUtil.checkPermissionAnd("user-update", "user-delete");        
// 校验:当前账号是否含有指定权限 [指定多个,只要其一验证通过即可]
StpUtil.checkPermissionOr("user-update", "user-delete");        

3.角色认证

在Sa-Token中,角色和权限可以独立验证

// 判断:当前账号是否拥有指定角色, 返回true或false
StpUtil.hasRole("super-admin");        
// 校验:当前账号是否含有指定角色标识, 如果验证未通过,则抛出异常: NotRoleException
StpUtil.checkRole("super-admin");        
// 校验:当前账号是否含有指定角色标识 [指定多个,必须全部验证通过]
StpUtil.checkRoleAnd("super-admin", "shop-admin");        
// 校验:当前账号是否含有指定角色标识 [指定多个,只要其一验证通过即可] 
StpUtil.checkRoleOr("super-admin", "shop-admin");  

4.权限通配符

Sa-Token允许你根据通配符指定泛权限,例如当一个账号拥有user*的权限时,user-adduser-deleteuser-update都将匹配通过

当一个账号拥有 "*" 权限时,他可以验证通过任何权限码 (角色认证同理)

// 当拥有 user* 权限时
StpUtil.hasPermission("user-add");        // true
StpUtil.hasPermission("user-update");     // true
StpUtil.hasPermission("art-add");         // false
// 当拥有 *-delete 权限时
StpUtil.hasPermission("user-add");        // false
StpUtil.hasPermission("user-delete");     // true
StpUtil.hasPermission("art-delete");      // true
// 当拥有 *.js 权限时
StpUtil.hasPermission("index.js");        // true
StpUtil.hasPermission("index.css");       // false
StpUtil.hasPermission("index.html");      // false

5.测试controller

// 测试角色接口, 浏览器访问: http://localhost:8081/user/testRole
    @RequestMapping("testRole")
    public SaResult testRole() {
        System.out.println("======================= 进入方法,测试角色接口 ========================= ");
        System.out.println("是否具有角色标识 user " + StpUtil.hasRole("user"));
        System.out.println("是否具有角色标识 admin " + StpUtil.hasRole("admin"));
        System.out.println("没有admin权限就抛出异常");
        StpUtil.checkRole("admin");
        System.out.println("在【admin、user】中只要拥有一个就不会抛出异常");
        StpUtil.checkRoleOr("admin", "user");
        System.out.println("在【admin、user】中必须全部拥有才不会抛出异常");
        StpUtil.checkRoleAnd("admin", "user");
        System.out.println("角色测试通过");
        return SaResult.ok();
    }
    // 测试权限接口, 浏览器访问: http://localhost:8081/user/testJur
    @RequestMapping("testJur")
    public SaResult testJur() {
        System.out.println("======================= 进入方法,测试权限接口 ========================= ");
        System.out.println("是否具有权限101" + StpUtil.hasPermission("101"));
        System.out.println("是否具有权限user-add" + StpUtil.hasPermission("user-add"));
        System.out.println("是否具有权限article-get" + StpUtil.hasPermission("article-get"));
        System.out.println("没有user-add权限就抛出异常");
        StpUtil.checkPermission("user-add");
        System.out.println("在【101、102】中只要拥有一个就不会抛出异常");
        StpUtil.checkPermissionOr("101", "102");
        System.out.println("在【101、102】中必须全部拥有才不会抛出异常");
        StpUtil.checkPermissionAnd("101", "102");
        System.out.println("权限测试通过");
        return SaResult.ok();
    }

六、注解式鉴权

  • @SaCheckLogin: 登录认证 —— 只有登录之后才能进入该方法
  • @SaCheckRole("admin"): 角色认证 —— 必须具有指定角色标识才能进入该方法
  • @SaCheckPermission("user:add"): 权限认证 —— 必须具有指定权限才能进入该方法
  • @SaCheckSafe: 二级认证校验 —— 必须二级认证之后才能进入该方法
  • @SaCheckBasic: HttpBasic认证 —— 只有通过 Basic 认证后才能进入该方法

1.注册拦截器

@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
    // 注册Sa-Token的注解拦截器,打开注解式鉴权功能 
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册注解拦截器,并排除不需要注解鉴权的接口地址 (与登录拦截器无关)
        registry.addInterceptor(new SaAnnotationInterceptor()).addPathPatterns("/**");    
    }
}

在高版本 SpringBoot (≥2.6.x) 版本下,需要额外添加 @EnableWebMvc 注解才可以使注册拦截器生效

2.使用注解鉴权

    // 登录认证:只有登录之后才能进入该方法   http://localhost:8081/user/info
    @SaCheckLogin
    @RequestMapping("/info")
    public String info() {
        return "查询用户信息";
    }
    // 角色认证:必须具有指定角色才能进入该方法  http://localhost:8081/user/add
    @SaCheckRole("super-admin")
    @RequestMapping("/add")
    public String add() {
        return "用户增加";
    }

3.设定校验模式

@SaCheckRole@SaCheckPermission注解可设置校验模式

    // 注解式鉴权:只要具有其中一个权限即可通过校验
    @RequestMapping("atJurOr")
    @SaCheckPermission(value = {"user-add", "user-all", "user-delete"}, mode = SaMode.OR)
    public SaResult atJurOr() {
        return SaResult.ok("用户信息");
    }
  • SaMode.AND, 标注一组权限,会话必须全部具有才可通过校验
  • SaMode.OR, 标注一组权限,会话只要具有其一即可通过校验

4.角色权限双重校验

    // 注解式鉴权:只要具有其中一个权限即可通过校验
    @RequestMapping("userAdd")
    @SaCheckPermission(value = "user-add", orRole = "admin")
    public SaResult userAdd() {
        return SaResult.ok("用户信息");
    }

orRole 字段代表权限认证未通过时的次要选择,两者只要其一认证成功即可通过校验,其有三种写法:

  • 写法一:orRole = "admin",代表需要拥有角色 admin 。
  • 写法二:orRole = {"admin", "manager", "staff"},代表具有三个角色其一即可。
  • 写法三:orRole = {"admin, manager, staff"},代表必须同时具有三个角色

七、整合redis

1.添加依赖

 	<!-- sa-token整合redis (使用jackson序列化方式) -->
         <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-dao-redis-jackson</artifactId>
            <version>${sa-token-version}</version>
        </dependency>
        <!-- 提供redis连接池 -->
         <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

2.redis配置类

@Configuration
public class RedisConfiguration{
    //配置redis的过期时间
    private static final StringRedisSerializer STRING_SERIALIZER = new StringRedisSerializer();
    private static final GenericJackson2JsonRedisSerializer JSON_SERIALIZER = new GenericJackson2JsonRedisSerializer();
    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(lettuceConnectionFactory);
        //key的序列方式
        template.setKeySerializer(STRING_SERIALIZER);
        //hashKey的序列方式
        template.setHashKeySerializer(STRING_SERIALIZER);
        //value的序列方式
        template.setValueSerializer(JSON_SERIALIZER);
        //value hashmap序列化
        template.setHashValueSerializer(JSON_SERIALIZER);
        return template;
    }
    @Bean
    public GenericObjectPoolConfig poolConfig(){
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        //控制一个pool可分配多少个jedis实例
        poolConfig.setMaxTotal(500);
        //最大空闲数
        poolConfig.setMaxIdle(200);
        //每次释放连接的最大数目,默认是3
        poolConfig.setNumTestsPerEvictionRun(1024);
        //逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
        poolConfig.setTimeBetweenEvictionRunsMillis(30000);
        //连接的最小空闲时间 默认1800000毫秒(30分钟)
        poolConfig.setMinEvictableIdleTimeMillis(-1);
        poolConfig.setSoftMinEvictableIdleTimeMillis(10000);
        //最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
        poolConfig.setMaxWaitMillis(1500);
        poolConfig.setTestOnBorrow(true);
        poolConfig.setTestWhileIdle(true);
        poolConfig.setTestOnReturn(false);
        poolConfig.setJmxEnabled(true);
        poolConfig.setBlockWhenExhausted(false);
        return poolConfig;
    }
    @Bean
    public LettuceConnectionFactory lettuceConnectionFactory() {
        LettucePoolingClientConfiguration lettucePoolingClientConfiguration = LettucePoolingClientConfiguration.builder()
                .poolConfig(poolConfig())
                .build();
        // 单机redis
        RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration();
        redisConfig.setHostName("127.0.0.1");
        redisConfig.setPort(6379);
        redisConfig.setDatabase(0);
        // 哨兵redis
        //RedisSentinelConfiguration redisConfig = new RedisSentinelConfiguration();
        // 集群redis
//        RedisClusterConfiguration redisConfig = new RedisClusterConfiguration();
//        Set<RedisNode> nodeses = new HashSet<>();
//        String[] hostses = nodes.split("-");
//        for (String h : hostses) {
//            h = h.replaceAll("\\s", "").replaceAll("\n", "");
//            if (!"".equals(h)) {
//                String host = h.split(":")[0];
//                int port = Integer.valueOf(h.split(":")[1]);
//                nodeses.add(new RedisNode(host, port));
//            }
//        }
//        redisConfig.setClusterNodes(nodeses);
//        // 跨集群执行命令时要遵循的最大重定向数量
//        redisConfig.setMaxRedirects(3);
//        redisConfig.setPassword(password);
        return new LettuceConnectionFactory(redisConfig, lettucePoolingClientConfiguration);
    }
}

Sa-Token-Redis 集成包的版本尽量与 Sa-Token-Starter 集成包的版本一致,否则可能出现兼容性问题

调用登录接口后,查看redis可视化界面

在这里插入图片描述

到此这篇关于springboot 整合 sa-token的文章就介绍到这了,更多相关springboot 整合sa-token内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

springboot整合sa-token简介及入门教程

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

springboot整合sa-token简介及入门教程

Sa-Token是一个轻量级Java权限认证框架,主要解决:登录认证、权限认证、Session会话、单点登录、OAuth2.0、微服务网关鉴权等一系列权限相关问题,这篇文章主要介绍了springboot整合sa-token简介及入门教程,需要的朋友可以参考下
2023-05-20

minio安装配置教程及整合springboot(史上最强保姆级教程---minio入门)

minio安装配置教程及整合springboot 1、进入minio官网2、选择放置minio文件路径3、根据命令行提示访问minio面板4、minio配置(yaml文件版)5、编写minio的配置文件MinIoClientConf
2023-08-22

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录