在现代Web应用中,Token与Redis的结合使用已成为一种常见的身份验证和授权机制。
Token的作用:会话跟踪,每次客户端携带token访问服务器,服务器端校验token的正确性。
好处:
-
灵活的过期策略:Redis可以设置Token的过期时间,一旦过期,系统需要重新验证用户身份。通过合理地设置过期时间,可以提高系统的安全性和性能。
-
安全性:Token通常包含敏感信息,如用户ID、权限等。将这些信息存储在Redis中,并采取适当的安全措施(如加密传输、访问控制等),可以保护Token不被未授权访问或篡改
JWT口令(token)
JSON Web Token(JWT)是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519)。
JWT由三部分组成,分别是头部(Header)、负载(Payload)、签名(Signature),中间以(.)分隔
其中Healder是现阶段使用过的
Header中存储了所使用的加密算法和Token类型,例如:
{
"alg": "HS256",
"typ": "JWT"
}
若想会用token,先在pom.xml中导入依赖
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.2.0</version>
</dependency>
之后,我们要创建token工具类
@Component
public class TokenUtil {
private static final Logger logger = LoggerFactory.getLogger(TokenUtil.class);
/**
* 过期时间
*/
private static String accessTokenExpireTime;
/**
* JWT认证加密私钥(Base64加密)
*/
private static String encryptJWTKey;
/**
* 解决@Value不能修饰static的问题
*/
@Value("${accessTokenExpireTime}")
public void setAccessTokenExpireTime(String accessTokenExpireTime) {
TokenUtil.accessTokenExpireTime = accessTokenExpireTime;
}
@Value("${encryptJWTKey}")
public void setEncryptJWTKey(String encryptJWTKey) {
TokenUtil.encryptJWTKey = encryptJWTKey;
}
public static String encode(String str) throws Exception {
byte[] encodeBytes = Base64.getEncoder().encode(str.getBytes("utf-8"));
return new String(encodeBytes);
}
public static String decode(String str) throws Exception {
byte[] decodeBytes = Base64.getDecoder().decode(str.getBytes("utf-8"));
return new String(decodeBytes);
}
public static void main(String[] args){
System.out.println(new Date(System.currentTimeMillis() + 300*1000));
}
/**
* 生成口令
* @param loginname 登录名
* @return String 口令
*/
public static String sign(String loginname) throws Exception {
try {
// 使用私钥进行加密
String secret = loginname + encode(encryptJWTKey);
// 设置过期时间:根据当前时间计算出过期时间。此处过期时间是以毫秒为单位,所以乘以1000。
Date date = new Date(System.currentTimeMillis() + Long.parseLong(accessTokenExpireTime) * 1000);
// 对私钥进行再次加密
Algorithm algorithm = Algorithm.HMAC256(secret);
// 生成token 附带loginname信息
String token = JWT.create().
withClaim("loginname", loginname)
.withClaim("currentTimeMillis", System.currentTimeMillis())
.withExpiresAt(date)
.sign(algorithm);
return token;
} catch (Exception e) {
e.printStackTrace();
logger.error("JWTToken加密出现异常:" + e.getMessage());
throw new Exception("JWTToken加密出现异常:" + e.getMessage());
}
}
/**
* 检验token是否有效
* @param token 口令
* @return boolean有效为true
*/
public static boolean verify(String token) {
try {
// 通过token获取登录名
String secret = getClaim(token, "loginname") + encode(encryptJWTKey);
// 进行二次加密
Algorithm algorithm = Algorithm.HMAC256(secret);
// 使用JWTVerifier进行验证解密
JWTVerifier verifier = JWT.require(algorithm).build();
verifier.verify(token);
return true;
} catch (Exception e) {
//e.printStackTrace();
//4logger.error("JWTToken认证解密出现UnsupportedEncodingException异常:" + e.getMessage());
return false;
}
}
/**
* 获取token中的信息就是withClaim中设置的值
* @param token 口令
* @param claim sign()方法中withClaim设置的key
* @return String 值
*/
public static String getClaim(String token, String claim) throws Exception {
try {
// 对token进行解码获得解码后的jwt
DecodedJWT jwt = JWT.decode(token);
// 获取到指定的claim,如果是其他类型返回null
return jwt.getClaim(claim).asString();
} catch (Exception e) {
//e.printStackTrace();
//logger.error("解密Token中的公共信息出现异常:" + e.getMessage());
throw new Exception("解密Token中的公共信息出现异常:" + e.getMessage());
}
}
}
这里面@Value中的${...}是 配置文件application中配置的内容
Token工具类中的常用方法
sign()方法:对指定字段进行加密
- 签名生成:
- sign() 方法用于对Token进行签名。它确保Token的内容在传输过程中未被篡改。
- 通过指定的签名算法(如HMAC SHA256)和密钥对Token的头部和负载部分进行加密,生成一个签名部分。
getClaim()方法
- 声明获取:
- getClaim() 方法用于从已解码的JWT中获取特定的声明(Claim)。
- 它返回一个Claim对象,该对象包含声明的名称和值,可以通过asXXX()方法将其转换为相应的数据类型(如String、Integer等)。
verify()方法
- Token验证:
- verify() 方法用于验证Token的合法性。它检查Token的签名是否正确,以确保Token未被篡改且是由可信的签发者签发的。
- 如果Token合法,该方法将返回一个解析后的JWT对象;如果不合法,则会抛出异常。
Html中的常用方法
1. SessionStorage: html5的功能,可以在会话期间保存键值对,取得值,删除键值对。
sessionStorage.setItem(key, value) ; 保存
sessionStorage.getItem(key): 取得
sessionStorage.removeItem(key); 删除。
2. localStorage: html5的功能,在前端浏览器中保存数据,数据会一直存储,直到主动删除。
配置完pom.xml,创建完工具类,便可以使用了,在要使用的地方使用@Autowired注入工具类
使用工具类中的 sign()方法给字段加密,返回前台
此时已经与Redis联动,使用了StringRedisTemPlate,第二行先忽略
返回的ResponseResult涉及到了统一异常处理和响应类
前台:登录成功的话,前端接收后台return的token,并保存键值对。
通过token,以后便可以配置鉴权拦截器了。(都已与Redis联合)
若登录成功,便可以根据token查到对应的数据,若数据为空,说明没登录
便可以使用response.getWriter().write( s: "{\"code\":401}"); 给前端页面发送鉴权失败的响应(json格式),前端页面收到401会返回到对应页面
拦截器:
Redis
springBoot中集成Jedis,导入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置文件中进行相关配置
spring.redis.host=127.0.0.1 (系统有默认值,可以不写)
#Redis服务器连接端口
spring.redis.port=6379 (系统有默认值,可以不写)
#Redis服务器连接密码(默认为空)
spring.redis.password=123456
之后便可以注入,与token一同使用
标签:return,String,redis,JWT,token,Token,static,使用 From: https://blog.csdn.net/lxy20030530/article/details/143269173