目录
前言
sa-token官方文档:https://sa-token.cc
Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证 、权限认证 、单点登录 、OAuth2.0 、分布式Session会话 、微服务网关鉴权 等一系列权限相关问题。

本教程的环境是springboot 2.6,jdk1.8
1,依赖引入
sa-token依赖:
xml
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.39.0</version>
</dependency>
sa-token集成jwt:
xml
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jwt</artifactId>
<version>1.39.0</version>
</dependency>
sa-token集成redis
xml
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-redis-jackson</artifactId>
<version>1.39.0</version>
</dependency>
这里我用的是security带的BCrypt密码加密,所以还导入了:
xml
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
</dependency>
2,相关配置
springboot配置文件
需要注意集成redis后,要想redis起作用还需要将 is-read-cookie 设为 false
配置jwt密钥 jwt-secret-key 随便打个长的字符就行了
数据库和redis连接请自行设置
yaml
# sa-token 配置
sa-token:
# token 名称(同时也是 cookie 名称)
token-name: Authorization
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
timeout: 86400
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: false
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
is-share: false
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
token-style: uuid
# 配置jwt密钥
jwt-secret-key: sadfsadfasdfsdafasfdseafasfdsadfsadfsa
# token前缀
token-prefix: Bearer
# 是否输出操作日志
is-log: true
# 是否尝试从 cookie 里读取 Token,此值为 false 后,StpUtil.login(id) 登录时也不会再往前端注入Cookie
# 注意:当使用 redis 作为缓存数据时要将 此关闭,否则不会将redis作为缓存,而是继续使用cookie
is-read-cookie: false
配置类:
redis序列化:
java
package com.satokendemo.config;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(connectionFactory);
return redisTemplate;
}
}
配置集成jwt和加密的实例:
java
package com.satokendemo.config;
import cn.dev33.satoken.jwt.StpLogicJwtForSimple;
import cn.dev33.satoken.stp.StpLogic;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
public class SaTokenConfig {
/**
* 配置集成jwt
* @return StpLogic
*/
@Bean
public StpLogic getStpLogicJwt() {
return new StpLogicJwtForSimple();
}
/**
* 密码加密配置
* @return BCryptPasswordEncoder
*/
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder(){
return new BCryptPasswordEncoder();
}
}
配置拦截器,进行身份和权限校验:
该配置的作用是不拦截登录,注册和一些文档接口,即匿名访问。
其它的接口都拦截,并进行是否登录的校验,未登录的用户将无法访问。
java
package com.satokendemo.config;
import cn.dev33.satoken.fun.SaParamFunction;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMVCConfig implements WebMvcConfigurer {
/**
* 配置saToken的身份权限拦截器
*
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SaInterceptor(new SaParamFunction<Object>() {
// 是否登录
@Override
public void run(Object o) {
// 调用sa-token提供的方法,校验用户身份登录
// 该操作的官网文档地址:https://sa-token.cc/doc.html#/use/route-check
StpUtil.checkLogin();
}
}))
// 将所有路径都拦截
.addPathPatterns("/**")
// 排除不拦截的路径
.excludePathPatterns(
"/sysUser/login",
"/sysUser/register",
"/doc.html",
"/webjars/**",
"/swagger-resources"
);
}
}
3,登录与退出
代码:
StpUtil.login(): sa-token的登录方法,里面填入用户唯一标识,一般为用户id。因为集成了redis所以登录时会将会话信息存入redis中。同时生成token。token过期后redis中的数据也会被删除
StpUtil.getTokenValue():获取token的方法,登录之后调用,返回token,因为已经集成了jwt,所以返回的是 jwt token。
StpUtil.logout():退出登录的方法,调用后token将失效,且redis存储的信息也将被删除
获取登录用户的id方法:
java
package com.satokendemo.controller;
import cn.dev33.satoken.stp.StpUtil;
import com.satokendemo.result.Result;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequiredArgsConstructor
@RequestMapping("sysUser")
public class SysUserController {
private final BCryptPasswordEncoder bCryptPasswordEncoder;
// 登录接口
@PostMapping("/login")
public Result<String> login(@RequestBody Map<String,String> sysUser) {
if (!sysUser.containsKey("username") || !sysUser.containsKey("password")){
return Result.error(401,"用户名或密码为空");
}
String username = "admin";
// 使用 BCrypt 加密后的 123456
String password = "$2a$10$QIVz.q.uRrqYiiKzK60jGetU/mRWrgPzVoxesgUen3tDVXsfmKB0K";
if (sysUser.get("username").equals("admin")&& bCryptPasswordEncoder.matches(sysUser.get("password"),"$2a$10$QIVz.q.uRrqYiiKzK60jGetU/mRWrgPzVoxesgUen3tDVXsfmKB0K")){
StpUtil.login(1000); // 这里输入用户id
return Result.success(StpUtil.getTokenValue());
}
return Result.error(401,"用户名或密码错误");
}
// 退出登录接口
@PostMapping("/logout")
public Result<String> logout() {
// 调用sa-token的退出登录方法
StpUtil.logout();
return Result.success("退出成功");
}
}
