简介:讲解单机和分布式应用下登录校验,session共享,分布式缓存使用
1、单机tomcat应用登录检验
sesssion保存在浏览器和应用服务器会话之间
用户登录成功,服务端会保证一个session,当然会给客户端一个sessionId,
客户端会把sessionId保存在cookie中,每次请求都会携带这个sessionId
2、分布式应用中session共享
真实的应用不可能单节点部署,所以就有个多节点登录session共享的问题需要解决
1)tomcat支持session共享,但是有广播风暴;用户量大的时候,占用资源就严重,不推荐
2)使用redis存储token:
服务端使用UUID生成随机64位或者128位token,放入redis中,然后返回给客户端并存储在cookie中
用户每次访问都携带此token,服务端去redis中校验是否有此用户即可
微服务下登录检验解决方案 JWT讲解(推荐)
1、JWT 是一个开放标准,它定义了一种用于简洁,自包含的用于通信双方之间以 JSON 对象的形式安全传递信息的方法。
JWT 可以使用 HMAC 算法或者是 RSA 的公钥密钥对进行签名
简单来说,就是通过一定规范来生成token,然后可以通过解密算法逆向解密token,这样就可以获取用户信息
{
id:888,
name:'小D',
expire:10000
}
funtion 加密(object, appsecret){
xxxx
return base64( token);
}
function 解密(token ,appsecret){
xxxx
//成功返回true,失败返回false
}
优点:
1)生产的token可以包含基本信息,比如id、用户昵称、头像等信息,避免再次查库
2)存储在客户端,不占用服务端的内存资源
缺点:
token是经过base64编码,所以可以解码,因此token加密前的对象不应该包含敏感信息
如用户权限,密码等
2、JWT格式组成 头部、负载、签名
header+payload+signature
头部:主要是描述签名算法
负载:主要描述是加密对象的信息,如用户的id等,也可以加些规范里面的东西,如iss签发者,exp 过期时间,sub 面向的用户
签名:主要是把前面两部分进行加密,防止别人拿到token进行base解密后篡改token
3、关于jwt客户端存储
可以存储在cookie,localstorage和sessionStorage里面
JWT在java(Springboot)中的应用
- 引入相关依赖并开发JWT工具类
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
- 封装 JWT生成和解析token的工具类
package com.itzhongzi.videoedu.utils;
import com.itzhongzi.videoedu.domain.User;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
public class JwtUtils {
public static final String SUBJECT = "itzhongzi";
public static final long EXPIRE = 1000 * 60 * 60 * 24 * 7;
public static final String APPSECRET = "it666";
public static String geneJsonWebToken(User user) {
if (user == null || user.getId() == null || user.getName() == null || user.getHeadImg() == null) {
return null;
}
String token = Jwts.builder().setSubject(SUBJECT)
.claim("id", user.getId())
.claim("name", user.getName())
.claim("image", user.getHeadImg())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
.signWith(SignatureAlgorithm.HS256, APPSECRET)
.compact();
return token;
}
public static Claims checkJWT(String token) {
try {
final Claims claims = Jwts.parser().setSigningKey(APPSECRET)
.parseClaimsJws(token)
.getBody();
return claims;
} catch (Exception e) { }
return null;
}
}
- 测试 工具类
@Test
public void testJWT(){
User user = new User();
user.setId(999);
user.setHeadImg("www.itzhongzi.com");
user.setName("it");
String token = JwtUtils.geneJsonWebToken(user);
System.out.println("token: " + token);
}
@Test
public void testCheck(){
String token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJpdHpob25nemkiLCJpZCI6OTk5LCJuYW1lIjoiaXQiLCJpbWFnZSI6Ind3dy5pdHpob25nemkuY29tIiwiaWF0IjoxNTc2MDU1MjM0LCJleHAiOjE1NzY2NjAwMzR9.VH8f6579SJk74HaPGfzgp5tyKVgOwjmu8E96QoR3OVs";
Claims claims = JwtUtils.checkJWT(token);
if(claims != null) {
System.out.println(claims);
String name = (String) claims.get("name");
String img = (String) claims.get("image");
int id = (Integer) claims.get("id");
System.out.println(name);
System.out.println(img);
System.out.println(id);
} else {
System.out.println("解密失败,非法token");
}
- 测试结果