springboot 整合 sa-token簡(jiǎn)介及入門(mén)教程
springboot:整合sa-token
一、簡(jiǎn)介
Sa-Token 是一個(gè)輕量級(jí) Java 權(quán)限認(rèn)證框架,主要解決:登錄認(rèn)證、權(quán)限認(rèn)證、Session會(huì)話(huà)、單點(diǎn)登錄、OAuth2.0、微服務(wù)網(wǎng)關(guān)鑒權(quán) 等一系列權(quán)限相關(guān)問(wèn)題
二、入門(mén)程序
1.添加依賴(lài)
<!-- Sa-Token 權(quán)限認(rèn)證, 在線(xià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配置類(lèi)
@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名稱(chēng) (同時(shí)也是cookie名稱(chēng))
saTokenConfig.setTokenName(TOKEN_NAME);
// token有效期,單位s 默認(rèn)30天, -1代表永不過(guò)期
saTokenConfig.setTimeout(TIMEOUT);
// token臨時(shí)有效期 (指定時(shí)間內(nèi)無(wú)操作就視為token過(guò)期) 單位: 秒
saTokenConfig.setActivityTimeout(ACTIVITY_TIMEOUT);
// 是否允許同一賬號(hào)并發(fā)登錄 (為true時(shí)允許一起登錄, 為false時(shí)新登錄擠掉舊登錄)
saTokenConfig.setAllowConcurrentLogin(true);
// 在多人登錄同一賬號(hào)時(shí),是否共用一個(gè)token (為true時(shí)所有登錄共用一個(gè)token, 為false時(shí)每次登錄新建一個(gè)token)
saTokenConfig.setIsShare(true);
// token風(fēng)格
saTokenConfig.setTokenStyle(TOKEN_STYLE);
return saTokenConfig;
}
}3.測(cè)試controller
@RestController
@RequestMapping("/user/")
public class UserController {
// 測(cè)試登錄,瀏覽器訪(fǎng)問(wèn): http://localhost:8081/user/doLogin?username=zhang&password=123456
@RequestMapping("doLogin")
public String doLogin(String username, String password) {
// 此處僅作模擬示例,真實(shí)項(xiàng)目需要從數(shù)據(jù)庫(kù)中查詢(xún)數(shù)據(jù)進(jìn)行比對(duì)
if("zhang".equals(username) && "123456".equals(password)) {
StpUtil.login(10001);
return "登錄成功";
}
return "登錄失敗";
}
// 查詢(xún)登錄狀態(tài),瀏覽器訪(fǎng)問(wèn): http://localhost:8081/user/isLogin
@RequestMapping("isLogin")
public String isLogin() {
return "當(dāng)前會(huì)話(huà)是否登錄:" + StpUtil.isLogin();
}
}三、認(rèn)證登錄
1.mysql配置類(lèi)
@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í)體類(lèi)
@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.測(cè)試controller
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserMapper userMapper;
//創(chuàng)建用戶(hù) ---- 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("登錄失敗");
}
// 查詢(xún)登錄狀態(tài) ---- http://localhost:8081/user/isLogin
@RequestMapping("isLogin")
public SaResult isLogin() {
return SaResult.ok("是否登錄:" + StpUtil.isLogin());
}
// 查詢(xún) Token 信息 ---- http://localhost:8081/user/tokenInfo
@RequestMapping("tokenInfo")
public SaResult tokenInfo() {
return SaResult.data(StpUtil.getTokenInfo());
}
// 測(cè)試注銷(xiāo) ---- 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.對(duì)稱(chēng)加密
// 定義秘鑰和明文
String key = "123456";
String text = "Sa-Token 一個(gè)輕量級(jí)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.非對(duì)稱(chēng)加密
// 定義私鑰和公鑰
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 一個(gè)輕量級(jí)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); // 生成一對(duì)公鑰和私鑰,其中Map對(duì)象 (private=私鑰, public=公鑰) System.out.println(SaSecureUtil.rsaGenerateKeyPair());
4.Base64編碼與解碼
// 文本
String text = "Sa-Token 一個(gè)輕量級(jí)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)前賬號(hào)權(quán)限碼集合
/**
* 自定義權(quán)限驗(yàn)證接口擴(kuò)展
*/
@Component // 打開(kāi)此注解,保證此類(lèi)被springboot掃描,即可完成sa-token的自定義權(quán)限驗(yàn)證擴(kuò)展
public class StpInterfaceImpl implements StpInterface {
/**
* 返回一個(gè)賬號(hào)所擁有的權(quán)限碼集合
*/
@Override
public List<String> getPermissionList(Object loginId, String loginKey) {
// 本list僅做模擬,實(shí)際項(xiàng)目中要根據(jù)具體業(yè)務(wù)邏輯來(lái)查詢(xún)權(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;
}
/**
* 返回一個(gè)賬號(hào)所擁有的角色標(biāo)識(shí)集合
*/
@Override
public List<String> getRoleList(Object loginId, String loginKey) {
// 本list僅做模擬,實(shí)際項(xiàng)目中要根據(jù)具體業(yè)務(wù)邏輯來(lái)查詢(xún)角色
List<String> list = new ArrayList<>();
list.add("admin");
list.add("super-admin");
return list;
}
}2.權(quán)限認(rèn)證
// 判斷:當(dāng)前賬號(hào)是否含有指定權(quán)限, 返回true或false
StpUtil.hasPermission("user-update");
// 校驗(yàn):當(dāng)前賬號(hào)是否含有指定權(quán)限, 如果驗(yàn)證未通過(guò),則拋出異常: NotPermissionException
StpUtil.checkPermission("user-update");
// 校驗(yàn):當(dāng)前賬號(hào)是否含有指定權(quán)限 [指定多個(gè),必須全部驗(yàn)證通過(guò)]
StpUtil.checkPermissionAnd("user-update", "user-delete");
// 校驗(yàn):當(dāng)前賬號(hào)是否含有指定權(quán)限 [指定多個(gè),只要其一驗(yàn)證通過(guò)即可]
StpUtil.checkPermissionOr("user-update", "user-delete"); 3.角色認(rèn)證
在Sa-Token中,角色和權(quán)限可以獨(dú)立驗(yàn)證
// 判斷:當(dāng)前賬號(hào)是否擁有指定角色, 返回true或false
StpUtil.hasRole("super-admin");
// 校驗(yàn):當(dāng)前賬號(hào)是否含有指定角色標(biāo)識(shí), 如果驗(yàn)證未通過(guò),則拋出異常: NotRoleException
StpUtil.checkRole("super-admin");
// 校驗(yàn):當(dāng)前賬號(hào)是否含有指定角色標(biāo)識(shí) [指定多個(gè),必須全部驗(yàn)證通過(guò)]
StpUtil.checkRoleAnd("super-admin", "shop-admin");
// 校驗(yàn):當(dāng)前賬號(hào)是否含有指定角色標(biāo)識(shí) [指定多個(gè),只要其一驗(yàn)證通過(guò)即可]
StpUtil.checkRoleOr("super-admin", "shop-admin"); 4.權(quán)限通配符
Sa-Token允許你根據(jù)通配符指定泛權(quán)限,例如當(dāng)一個(gè)賬號(hào)擁有user*的權(quán)限時(shí),user-add、user-delete、user-update都將匹配通過(guò)
當(dāng)一個(gè)賬號(hào)擁有
"*"權(quán)限時(shí),他可以驗(yàn)證通過(guò)任何權(quán)限碼 (角色認(rèn)證同理)
// 當(dāng)擁有 user* 權(quán)限時(shí)
StpUtil.hasPermission("user-add"); // true
StpUtil.hasPermission("user-update"); // true
StpUtil.hasPermission("art-add"); // false
// 當(dāng)擁有 *-delete 權(quán)限時(shí)
StpUtil.hasPermission("user-add"); // false
StpUtil.hasPermission("user-delete"); // true
StpUtil.hasPermission("art-delete"); // true
// 當(dāng)擁有 *.js 權(quán)限時(shí)
StpUtil.hasPermission("index.js"); // true
StpUtil.hasPermission("index.css"); // false
StpUtil.hasPermission("index.html"); // false5.測(cè)試controller
// 測(cè)試角色接口, 瀏覽器訪(fǎng)問(wèn): http://localhost:8081/user/testRole
@RequestMapping("testRole")
public SaResult testRole() {
System.out.println("======================= 進(jìn)入方法,測(cè)試角色接口 ========================= ");
System.out.println("是否具有角色標(biāo)識(shí) user " + StpUtil.hasRole("user"));
System.out.println("是否具有角色標(biāo)識(shí) admin " + StpUtil.hasRole("admin"));
System.out.println("沒(méi)有admin權(quán)限就拋出異常");
StpUtil.checkRole("admin");
System.out.println("在【admin、user】中只要擁有一個(gè)就不會(huì)拋出異常");
StpUtil.checkRoleOr("admin", "user");
System.out.println("在【admin、user】中必須全部擁有才不會(huì)拋出異常");
StpUtil.checkRoleAnd("admin", "user");
System.out.println("角色測(cè)試通過(guò)");
return SaResult.ok();
}
// 測(cè)試權(quán)限接口, 瀏覽器訪(fǎng)問(wèn): http://localhost:8081/user/testJur
@RequestMapping("testJur")
public SaResult testJur() {
System.out.println("======================= 進(jìn)入方法,測(cè)試權(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("沒(méi)有user-add權(quán)限就拋出異常");
StpUtil.checkPermission("user-add");
System.out.println("在【101、102】中只要擁有一個(gè)就不會(huì)拋出異常");
StpUtil.checkPermissionOr("101", "102");
System.out.println("在【101、102】中必須全部擁有才不會(huì)拋出異常");
StpUtil.checkPermissionAnd("101", "102");
System.out.println("權(quán)限測(cè)試通過(guò)");
return SaResult.ok();
}六、注解式鑒權(quán)
@SaCheckLogin: 登錄認(rèn)證 —— 只有登錄之后才能進(jìn)入該方法@SaCheckRole("admin"): 角色認(rèn)證 —— 必須具有指定角色標(biāo)識(shí)才能進(jìn)入該方法@SaCheckPermission("user:add"): 權(quán)限認(rèn)證 —— 必須具有指定權(quán)限才能進(jìn)入該方法@SaCheckSafe: 二級(jí)認(rèn)證校驗(yàn) —— 必須二級(jí)認(rèn)證之后才能進(jìn)入該方法@SaCheckBasic: HttpBasic認(rèn)證 —— 只有通過(guò) Basic 認(rèn)證后才能進(jìn)入該方法
1.注冊(cè)攔截器
@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
// 注冊(cè)Sa-Token的注解攔截器,打開(kāi)注解式鑒權(quán)功能
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注冊(cè)注解攔截器,并排除不需要注解鑒權(quán)的接口地址 (與登錄攔截器無(wú)關(guān))
registry.addInterceptor(new SaAnnotationInterceptor()).addPathPatterns("/**");
}
}在高版本
SpringBoot (≥2.6.x)版本下,需要額外添加@EnableWebMvc注解才可以使注冊(cè)攔截器生效
2.使用注解鑒權(quán)
// 登錄認(rèn)證:只有登錄之后才能進(jìn)入該方法 http://localhost:8081/user/info
@SaCheckLogin
@RequestMapping("/info")
public String info() {
return "查詢(xún)用戶(hù)信息";
}
// 角色認(rèn)證:必須具有指定角色才能進(jìn)入該方法 http://localhost:8081/user/add
@SaCheckRole("super-admin")
@RequestMapping("/add")
public String add() {
return "用戶(hù)增加";
}3.設(shè)定校驗(yàn)?zāi)J?/h4>
@SaCheckRole與@SaCheckPermission注解可設(shè)置校驗(yàn)?zāi)J?/p>
// 注解式鑒權(quán):只要具有其中一個(gè)權(quán)限即可通過(guò)校驗(yàn)
@RequestMapping("atJurOr")
@SaCheckPermission(value = {"user-add", "user-all", "user-delete"}, mode = SaMode.OR)
public SaResult atJurOr() {
return SaResult.ok("用戶(hù)信息");
}SaMode.AND, 標(biāo)注一組權(quán)限,會(huì)話(huà)必須全部具有才可通過(guò)校驗(yàn)SaMode.OR, 標(biāo)注一組權(quán)限,會(huì)話(huà)只要具有其一即可通過(guò)校驗(yàn)
4.角色權(quán)限雙重校驗(yàn)
// 注解式鑒權(quán):只要具有其中一個(gè)權(quán)限即可通過(guò)校驗(yàn)
@RequestMapping("userAdd")
@SaCheckPermission(value = "user-add", orRole = "admin")
public SaResult userAdd() {
return SaResult.ok("用戶(hù)信息");
}orRole 字段代表權(quán)限認(rèn)證未通過(guò)時(shí)的次要選擇,兩者只要其一認(rèn)證成功即可通過(guò)校驗(yàn),其有三種寫(xiě)法:
- 寫(xiě)法一:
orRole = "admin",代表需要擁有角色 admin 。 - 寫(xiě)法二:
orRole = {"admin", "manager", "staff"},代表具有三個(gè)角色其一即可。 - 寫(xiě)法三:
orRole = {"admin, manager, staff"},代表必須同時(shí)具有三個(gè)角色
七、整合redis
1.添加依賴(lài)
<!-- 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配置類(lèi)
@Configuration
public class RedisConfiguration{
//配置redis的過(guò)期時(shí)間
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();
//控制一個(gè)pool可分配多少個(gè)jedis實(shí)例
poolConfig.setMaxTotal(500);
//最大空閑數(shù)
poolConfig.setMaxIdle(200);
//每次釋放連接的最大數(shù)目,默認(rèn)是3
poolConfig.setNumTestsPerEvictionRun(1024);
//逐出掃描的時(shí)間間隔(毫秒) 如果為負(fù)數(shù),則不運(yùn)行逐出線(xiàn)程, 默認(rèn)-1
poolConfig.setTimeBetweenEvictionRunsMillis(30000);
//連接的最小空閑時(shí)間 默認(rèn)1800000毫秒(30分鐘)
poolConfig.setMinEvictableIdleTimeMillis(-1);
poolConfig.setSoftMinEvictableIdleTimeMillis(10000);
//最大建立連接等待時(shí)間。如果超過(guò)此時(shí)間將接到異常。設(shè)為-1表示無(wú)限制。
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í)要遵循的最大重定向數(shù)量
// redisConfig.setMaxRedirects(3);
// redisConfig.setPassword(password);
return new LettuceConnectionFactory(redisConfig, lettucePoolingClientConfiguration);
}
}Sa-Token-Redis 集成包的版本盡量與 Sa-Token-Starter 集成包的版本一致,否則可能出現(xiàn)兼容性問(wèn)題
調(diào)用登錄接口后,查看redis可視化界面

到此這篇關(guān)于springboot 整合 sa-token的文章就介紹到這了,更多相關(guān)springboot 整合sa-token內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java基于控制臺(tái)界面實(shí)現(xiàn)ATM系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Java基于控制臺(tái)界面實(shí)現(xiàn)ATM系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
Java獲得一個(gè)數(shù)組的指定長(zhǎng)度排列組合算法示例
這篇文章主要介紹了Java獲得一個(gè)數(shù)組的指定長(zhǎng)度排列組合算法,結(jié)合實(shí)例形式分析了java排列組合相關(guān)數(shù)組遍歷、運(yùn)算操作技巧,需要的朋友可以參考下2019-06-06
簡(jiǎn)談java并發(fā)FutureTask的實(shí)現(xiàn)
這篇文章主要介紹了簡(jiǎn)談java并發(fā)FutureTask的實(shí)現(xiàn),FutureTask都是用于獲取線(xiàn)程執(zhí)行的返回結(jié)果。文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,,需要的朋友可以參考下2019-06-06
在controller中如何設(shè)置接收參數(shù)的默認(rèn)值
這篇文章主要介紹了在controller中如何設(shè)置接收參數(shù)的默認(rèn)值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
SpringBoot返回Json對(duì)象報(bào)錯(cuò)(返回對(duì)象為空{(diào)})
本文主要介紹介紹了SpringBoot返回Json對(duì)象報(bào)錯(cuò)(返回對(duì)象為空{(diào)}),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
簡(jiǎn)潔實(shí)用的Java Base64編碼加密異常處理類(lèi)代碼
這篇文章主要介紹了簡(jiǎn)潔實(shí)用的Java Base64編碼加密異常處理類(lèi)代碼,有一定的實(shí)用價(jià)值,需要的朋友可以參考下2014-07-07
MyBatis數(shù)據(jù)脫敏的實(shí)現(xiàn)方案介紹
在我們數(shù)據(jù)庫(kù)中有些時(shí)候會(huì)保存一些用戶(hù)的敏感信息,比如:手機(jī)號(hào)、銀行卡等信息,如果這些信息以明文的方式保存,那么是不安全的2022-08-08

