springboot 整合 sa-token簡介及入門教程
springboot:整合sa-token
一、簡介
Sa-Token 是一個輕量級 Java 權(quán)限認(rèn)證框架,主要解決:登錄認(rèn)證
、權(quán)限認(rèn)證
、Session會話
、單點(diǎn)登錄
、OAuth2.0
、微服務(wù)網(wǎng)關(guān)鑒權(quán)
等一系列權(quán)限相關(guān)問題
二、入門程序
1.添加依賴
<!-- Sa-Token 權(quán)限認(rèn)證, 在線文檔: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 默認(rèn)30天, -1代表永不過期 saTokenConfig.setTimeout(TIMEOUT); // token臨時有效期 (指定時間內(nèi)無操作就視為token過期) 單位: 秒 saTokenConfig.setActivityTimeout(ACTIVITY_TIMEOUT); // 是否允許同一賬號并發(fā)登錄 (為true時允許一起登錄, 為false時新登錄擠掉舊登錄) saTokenConfig.setAllowConcurrentLogin(true); // 在多人登錄同一賬號時,是否共用一個token (為true時所有登錄共用一個token, 為false時每次登錄新建一個token) saTokenConfig.setIsShare(true); // token風(fēng)格 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) { // 此處僅作模擬示例,真實(shí)項(xiàng)目需要從數(shù)據(jù)庫中查詢數(shù)據(jù)進(jìn)行比對 if("zhang".equals(username) && "123456".equals(password)) { StpUtil.login(10001); return "登錄成功"; } return "登錄失敗"; } // 查詢登錄狀態(tài),瀏覽器訪問: http://localhost:8081/user/isLogin @RequestMapping("isLogin") public String isLogin() { return "當(dāng)前會話是否登錄:" + StpUtil.isLogin(); } }
三、認(rèn)證登錄
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.實(shí)體類
@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; //創(chuàng)建用戶 ---- 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("登錄失敗"); } // 查詢登錄狀態(tài) ---- 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權(quán)限認(rèn)證框架"; // 加密 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權(quán)限認(rèn)證框架"; // 使用公鑰加密 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權(quán)限認(rèn)證框架"; // 使用Base64編碼 String base64Text = SaBase64Util.encode(text); System.out.println("Base64編碼后:" + base64Text); // 使用Base64解碼 String text2 = SaBase64Util.decode(base64Text); System.out.println("Base64解碼后:" + text2);
五、權(quán)限認(rèn)證
1.獲取當(dāng)前賬號權(quán)限碼集合
/** * 自定義權(quán)限驗(yàn)證接口擴(kuò)展 */ @Component // 打開此注解,保證此類被springboot掃描,即可完成sa-token的自定義權(quán)限驗(yàn)證擴(kuò)展 public class StpInterfaceImpl implements StpInterface { /** * 返回一個賬號所擁有的權(quán)限碼集合 */ @Override public List<String> getPermissionList(Object loginId, String loginKey) { // 本list僅做模擬,實(shí)際項(xiàng)目中要根據(jù)具體業(yè)務(wù)邏輯來查詢權(quán)限 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; } /** * 返回一個賬號所擁有的角色標(biāo)識集合 */ @Override public List<String> getRoleList(Object loginId, String loginKey) { // 本list僅做模擬,實(shí)際項(xiàng)目中要根據(jù)具體業(yè)務(wù)邏輯來查詢角色 List<String> list = new ArrayList<>(); list.add("admin"); list.add("super-admin"); return list; } }
2.權(quán)限認(rèn)證
// 判斷:當(dāng)前賬號是否含有指定權(quán)限, 返回true或false StpUtil.hasPermission("user-update"); // 校驗(yàn):當(dāng)前賬號是否含有指定權(quán)限, 如果驗(yàn)證未通過,則拋出異常: NotPermissionException StpUtil.checkPermission("user-update"); // 校驗(yàn):當(dāng)前賬號是否含有指定權(quán)限 [指定多個,必須全部驗(yàn)證通過] StpUtil.checkPermissionAnd("user-update", "user-delete"); // 校驗(yàn):當(dāng)前賬號是否含有指定權(quán)限 [指定多個,只要其一驗(yàn)證通過即可] StpUtil.checkPermissionOr("user-update", "user-delete");
3.角色認(rèn)證
在Sa-Token中,角色和權(quán)限可以獨(dú)立驗(yàn)證
// 判斷:當(dāng)前賬號是否擁有指定角色, 返回true或false StpUtil.hasRole("super-admin"); // 校驗(yàn):當(dāng)前賬號是否含有指定角色標(biāo)識, 如果驗(yàn)證未通過,則拋出異常: NotRoleException StpUtil.checkRole("super-admin"); // 校驗(yàn):當(dāng)前賬號是否含有指定角色標(biāo)識 [指定多個,必須全部驗(yàn)證通過] StpUtil.checkRoleAnd("super-admin", "shop-admin"); // 校驗(yàn):當(dāng)前賬號是否含有指定角色標(biāo)識 [指定多個,只要其一驗(yàn)證通過即可] StpUtil.checkRoleOr("super-admin", "shop-admin");
4.權(quán)限通配符
Sa-Token允許你根據(jù)通配符指定泛權(quán)限,例如當(dāng)一個賬號擁有user*
的權(quán)限時,user-add
、user-delete
、user-update
都將匹配通過
當(dāng)一個賬號擁有
"*"
權(quán)限時,他可以驗(yàn)證通過任何權(quán)限碼 (角色認(rèn)證同理)
// 當(dāng)擁有 user* 權(quán)限時 StpUtil.hasPermission("user-add"); // true StpUtil.hasPermission("user-update"); // true StpUtil.hasPermission("art-add"); // false // 當(dāng)擁有 *-delete 權(quán)限時 StpUtil.hasPermission("user-add"); // false StpUtil.hasPermission("user-delete"); // true StpUtil.hasPermission("art-delete"); // true // 當(dāng)擁有 *.js 權(quán)限時 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("======================= 進(jìn)入方法,測試角色接口 ========================= "); System.out.println("是否具有角色標(biāo)識 user " + StpUtil.hasRole("user")); System.out.println("是否具有角色標(biāo)識 admin " + StpUtil.hasRole("admin")); System.out.println("沒有admin權(quán)限就拋出異常"); 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(); } // 測試權(quán)限接口, 瀏覽器訪問: http://localhost:8081/user/testJur @RequestMapping("testJur") public SaResult testJur() { System.out.println("======================= 進(jìn)入方法,測試權(quán)限接口 ========================= "); System.out.println("是否具有權(quán)限101" + StpUtil.hasPermission("101")); System.out.println("是否具有權(quán)限user-add" + StpUtil.hasPermission("user-add")); System.out.println("是否具有權(quán)限article-get" + StpUtil.hasPermission("article-get")); System.out.println("沒有user-add權(quán)限就拋出異常"); 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("權(quán)限測試通過"); return SaResult.ok(); }
六、注解式鑒權(quán)
@SaCheckLogin
: 登錄認(rèn)證 —— 只有登錄之后才能進(jìn)入該方法@SaCheckRole("admin")
: 角色認(rèn)證 —— 必須具有指定角色標(biāo)識才能進(jìn)入該方法@SaCheckPermission("user:add")
: 權(quán)限認(rèn)證 —— 必須具有指定權(quán)限才能進(jìn)入該方法@SaCheckSafe
: 二級認(rèn)證校驗(yàn) —— 必須二級認(rèn)證之后才能進(jìn)入該方法@SaCheckBasic
: HttpBasic認(rèn)證 —— 只有通過 Basic 認(rèn)證后才能進(jìn)入該方法
1.注冊攔截器
@Configuration public class SaTokenConfigure implements WebMvcConfigurer { // 注冊Sa-Token的注解攔截器,打開注解式鑒權(quán)功能 @Override public void addInterceptors(InterceptorRegistry registry) { // 注冊注解攔截器,并排除不需要注解鑒權(quán)的接口地址 (與登錄攔截器無關(guān)) registry.addInterceptor(new SaAnnotationInterceptor()).addPathPatterns("/**"); } }
在高版本
SpringBoot (≥2.6.x)
版本下,需要額外添加@EnableWebMvc
注解才可以使注冊攔截器生效
2.使用注解鑒權(quán)
// 登錄認(rèn)證:只有登錄之后才能進(jìn)入該方法 http://localhost:8081/user/info @SaCheckLogin @RequestMapping("/info") public String info() { return "查詢用戶信息"; } // 角色認(rèn)證:必須具有指定角色才能進(jìn)入該方法 http://localhost:8081/user/add @SaCheckRole("super-admin") @RequestMapping("/add") public String add() { return "用戶增加"; }
3.設(shè)定校驗(yàn)?zāi)J?/h4>
@SaCheckRole
與@SaCheckPermission
注解可設(shè)置校驗(yàn)?zāi)J?/p>
// 注解式鑒權(quán):只要具有其中一個權(quán)限即可通過校驗(yàn) @RequestMapping("atJurOr") @SaCheckPermission(value = {"user-add", "user-all", "user-delete"}, mode = SaMode.OR) public SaResult atJurOr() { return SaResult.ok("用戶信息"); }
SaMode.AND
, 標(biāo)注一組權(quán)限,會話必須全部具有才可通過校驗(yàn)SaMode.OR
, 標(biāo)注一組權(quán)限,會話只要具有其一即可通過校驗(yàn)
4.角色權(quán)限雙重校驗(yàn)
// 注解式鑒權(quán):只要具有其中一個權(quán)限即可通過校驗(yàn) @RequestMapping("userAdd") @SaCheckPermission(value = "user-add", orRole = "admin") public SaResult userAdd() { return SaResult.ok("用戶信息"); }
orRole 字段代表權(quán)限認(rèn)證未通過時的次要選擇,兩者只要其一認(rèn)證成功即可通過校驗(yàn),其有三種寫法:
- 寫法一:
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實(shí)例 poolConfig.setMaxTotal(500); //最大空閑數(shù) poolConfig.setMaxIdle(200); //每次釋放連接的最大數(shù)目,默認(rèn)是3 poolConfig.setNumTestsPerEvictionRun(1024); //逐出掃描的時間間隔(毫秒) 如果為負(fù)數(shù),則不運(yùn)行逐出線程, 默認(rèn)-1 poolConfig.setTimeBetweenEvictionRunsMillis(30000); //連接的最小空閑時間 默認(rèn)1800000毫秒(30分鐘) poolConfig.setMinEvictableIdleTimeMillis(-1); poolConfig.setSoftMinEvictableIdleTimeMillis(10000); //最大建立連接等待時間。如果超過此時間將接到異常。設(shè)為-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(); // 單機(jī)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); // // 跨集群執(zhí)行命令時要遵循的最大重定向數(shù)量 // redisConfig.setMaxRedirects(3); // redisConfig.setPassword(password); return new LettuceConnectionFactory(redisConfig, lettucePoolingClientConfiguration); } }
Sa-Token-Redis 集成包的版本盡量與 Sa-Token-Starter 集成包的版本一致,否則可能出現(xiàn)兼容性問題
調(diào)用登錄接口后,查看redis可視化界面
到此這篇關(guān)于springboot 整合 sa-token的文章就介紹到這了,更多相關(guān)springboot 整合sa-token內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java基于控制臺界面實(shí)現(xiàn)ATM系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Java基于控制臺界面實(shí)現(xiàn)ATM系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-05-05簡談java并發(fā)FutureTask的實(shí)現(xiàn)
這篇文章主要介紹了簡談java并發(fā)FutureTask的實(shí)現(xiàn),FutureTask都是用于獲取線程執(zhí)行的返回結(jié)果。文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,,需要的朋友可以參考下2019-06-06在controller中如何設(shè)置接收參數(shù)的默認(rèn)值
這篇文章主要介紹了在controller中如何設(shè)置接收參數(shù)的默認(rèn)值,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03SpringBoot返回Json對象報錯(返回對象為空{(diào)})
本文主要介紹介紹了SpringBoot返回Json對象報錯(返回對象為空{(diào)}),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01簡潔實(shí)用的Java Base64編碼加密異常處理類代碼
這篇文章主要介紹了簡潔實(shí)用的Java Base64編碼加密異常處理類代碼,有一定的實(shí)用價值,需要的朋友可以參考下2014-07-07MyBatis數(shù)據(jù)脫敏的實(shí)現(xiàn)方案介紹
在我們數(shù)據(jù)庫中有些時候會保存一些用戶的敏感信息,比如:手機(jī)號、銀行卡等信息,如果這些信息以明文的方式保存,那么是不安全的2022-08-08