向spring容器中加入一下类:用于重写:
cn.dev33
sa-token-spring-boot-starter
1.19.0
cn.dev33
sa-token-spring-aop
1.19.0
com.auth0
java-jwt
3.8.2
io.jsonwebtoken
jjwt
0.9.0
import java.util.Date;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.context.model.SaStorage;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaTokenConsts;
import io.jsonwebtoken.*;
import org.springframework.stereotype.Component;
/**
* sa-token集成Jwt
*
* @author Lenovo
*/
@Component
public class SaTokenJwtUtil {
/**
* 秘钥 (随便手打几个字母就好了)
*/
public static final String BASE64_SECURITY = "79e7c69681b8270162386e6daa53d1dd";
/**
* token有效期 (单位: 秒)
*/
public static final long TIMEOUT = 60 * 60 * 2;
public static final String LOGIN_ID_KEY = "loginId";
/**
* 根据userId生成token
*
* @param loginId 账号id
* @return jwt-token
*/
public static String createToken(Object loginId) {
// 判断,不可使用默认秘钥
// if(BASE64_SECURITY.equals("79e7c69681b8270162386e6daa53d1dd")) {
// throw new SaTokenException("请更换秘钥");
// }
// 在这里你可以使用官方提供的claim方法构建载荷,也可以使用setPayload自定义载荷,但是两者不可一起使用
JwtBuilder builder = Jwts.builder()
.setHeaderParam("type", "JWT")
.claim(LOGIN_ID_KEY, loginId)
.setIssuedAt(new Date()) // 签发日期
.setExpiration(new Date(System.currentTimeMillis() + 1000 * TIMEOUT)) // 有效截止日期
.signWith(SignatureAlgorithm.HS256, BASE64_SECURITY.getBytes()); // 加密算法
//生成JWT
return builder.compact();
}
/**
* 从一个jwt里面解析出Claims
*
* @param tokenValue token值
* @return Claims对象
*/
public static Claims getClaims(String tokenValue) {
// System.out.println(tokenValue);
Claims claims = Jwts.parser()
.setSigningKey(BASE64_SECURITY.getBytes())
.parseClaimsJws(tokenValue).getBody();
return claims;
}
/**
* 从一个jwt里面解析loginId
*
* @param tokenValue token值
* @return loginId
*/
public static String getLoginId(String tokenValue) {
try {
Object loginId = getClaims(tokenValue).get(LOGIN_ID_KEY);
if (loginId == null) {
return null;
}
return String.valueOf(loginId);
} catch (ExpiredJwtException e) {
// throw NotLoginException.newInstance(StpUtil.stpLogic.loginKey, NotLoginException.TOKEN_TIMEOUT);
return NotLoginException.TOKEN_TIMEOUT;
} catch (MalformedJwtException e) {
throw NotLoginException.newInstance(StpUtil.stpLogic.loginKey, NotLoginException.INVALID_TOKEN);
} catch (Exception e) {
throw new SaTokenException(e);
}
}
static {
// 判断秘钥
if (BASE64_SECURITY.equals("79e7c69681b8270162386e6daa53d1dd")) {
String warn = "-------------------------------------\n";
warn += "请更换JWT秘钥,不要使用示例默认秘钥\n";
warn += "-------------------------------------";
System.err.println(warn);
}
// 修改默认实现
StpUtil.stpLogic = new StpLogic("login") {
// 重写 (随机生成一个tokenValue)
@Override
public String createTokenValue(Object loginId) {
return SaTokenJwtUtil.createToken(loginId);
}
// 重写 (在当前会话上登录id )
@Override
public void setLoginId(Object loginId, SaLoginModel loginModel) {
// ------ 1、获取相应对象
SaStorage storage = SaManager.getSaTokenContext().getStorage();
SaTokenConfig config = getConfig();
// ------ 2、生成一个token
String tokenValue = createTokenValue(loginId);
storage.set(splicingKeyJustCreatedSave(), tokenValue); // 将token保存到本次request里
if (config.getIsReadCookie() == true) { // cookie注入
SaManager.getSaTokenContext().getResponse().addCookie(getTokenName(), tokenValue, "/", config.getCookieDomain(), (int) config.getTimeout());
}
}
// 重写 (获取指定token对应的登录id)
@Override
public String getLoginIdNotHandle(String tokenValue) {
try {
return SaTokenJwtUtil.getLoginId(tokenValue);
} catch (Exception e) {
return null;
}
}
// 重写 (当前会话注销登录)
@Override
public void logout() {
// 如果连token都没有,那么无需执行任何操作
String tokenValue = getTokenValue();
if (tokenValue == null) {
return;
}
// 如果打开了cookie模式,把cookie清除掉
if (getConfig().getIsReadCookie() == true) {
SaManager.getSaTokenContext().getResponse().deleteCookie(getTokenName());
}
}
// 重写 (获取指定key的session)
@Override
public SaSession getSessionBySessionId(String sessionId, boolean isCreate) {
throw new SaTokenException("jwt has not session");
}
// 重写 (获取当前登录者的token剩余有效时间 (单位: 秒))
@Override
public long getTokenTimeout() {
// 如果没有token
String tokenValue = getTokenValue();
if (tokenValue == null) {
return SaTokenDao.NOT_VALUE_EXPIRE;
}
// 开始取值
Claims claims = null;
try {
claims = SaTokenJwtUtil.getClaims(tokenValue);
} catch (Exception e) {
return SaTokenDao.NOT_VALUE_EXPIRE;
}
if (claims == null) {
return SaTokenDao.NOT_VALUE_EXPIRE;
}
Date expiration = claims.getExpiration();
if (expiration == null) {
return SaTokenDao.NOT_VALUE_EXPIRE;
}
return (expiration.getTime() - System.currentTimeMillis()) / 1000;
}
// 重写 (返回当前token的登录设备)
@Override
public String getLoginDevice() {
return SaTokenConsts.DEFAULT_LOGIN_DEVICE;
}
// 重写 (获取当前会话的token信息)
@Override
public SaTokenInfo getTokenInfo() {
SaTokenInfo info = new SaTokenInfo();
info.tokenName = getTokenName();
info.tokenValue = getTokenValue();
info.isLogin = isLogin();
info.loginId = getLoginIdDefaultNull();
info.loginKey = getLoginKey();
info.tokenTimeout = getTokenTimeout();
// info.sessionTimeout = getSessionTimeout();
// info.tokenSessionTimeout = getTokenSessionTimeout();
// info.tokenActivityTimeout = getTokenActivityTimeout();
info.loginDevice = getLoginDevice();
return info;
}
};
}
}
使用:
import com.alibaba.fastjson.JSON;
import com.example.mindsa.util.UserInfo;
import com.example.mindsa.util.result.AjaxJson;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import cn.dev33.satoken.stp.StpUtil;
@RestController
@RequestMapping("/test/")
public class TestJwtController {
//登录
@RequestMapping("login")
public AjaxJson login(@RequestParam(defaultValue = "10001") String id) {
UserInfo userInfo = new UserInfo();
userInfo.setName("中国好声音");
StpUtil.setLoginId(JSON.toJSONString(userInfo));
String token = StpUtil.getTokenValue();
return AjaxJson.getSuccess(token);
}
//使用-
@RequestMapping("tokenInfo")
public AjaxJson tokenInfo() {
UserInfo userInfo = JSON.parseObject(StpUtil.getLoginId().toString(), UserInfo.class);
return AjaxJson.getSuccessData(userInfo);
}
//使用-如何是第三方跳转登录,可以把token放到Cookie,也可以放到Head头里面
@RequestMapping("tokenInfo2")
public AjaxJson tokenInfo2(@RequestHeader String satoken) {
UserInfo userInfo = JSON.parseObject(StpUtil.getLoginId().toString(), UserInfo.class);
return AjaxJson.getSuccessData(userInfo);
}
}
//手动解析token
public class ApplicationController extends BaseController {
static String token = "eyJ0eXBlIjoiSldUIiwiYWxnIjoiSFMyNTYifQ.eyJsb2dpbklkIjoie1wiZW1haWxcIjpcIlwiLFwibmFtZVwiOm51bGwsXCJvcmdpZFwiOlwiMFwiLFwicGhvbmVcIjpcIlwiLFwidXNlcm5hbWVcIjpcInpoaWh1emhleWVcIn0iLCJpYXQiOjE2MzIyODEyMzAsImV4cCI6MTY2MzgxNzIzMH0.BL9bTTqeWviD4rPD7L_6tygz6Q78fJ7YBTY3yEPuLUA";
public static void main(String[] args) {
//手动生成token
String mytoken = SaTokenJwtUtil.createToken("loginId");
//手动解析token
Claims claims = SaTokenJwtUtil.getClaims(token);
System.out.println(claims);
}
}