文章目录
1.Session认证
1.1 认证过程
用户----发送用户名和密码—>服务器
服务器: 验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等。
服务器---- 返回一个 session_id----->用户: 写入用户的 Cookie。
用户----发送请求,传回cookie中的session_id–>服务器
服务器 -----根据session_id查询到用户信息,返回user----> 用户
1.2 缺陷
session 认证的方式应用非常普遍,但也存在一些问题,扩展性不好。如果是服务器集群,或者是跨域的服务导向架构,就要求 session 数据共享,每台服务器都能够读取 session。
1.3 解决方法
way1:
session 数据持久化,写入数据库或别的持久层。各种服务收到请求后,都向持久层请求数据。这种方案的优点是架构清晰,缺点是工程量比较大。
way2:
所有数据都保存在客户端,服务器不再保存 session 数据,每次请求都发回服务器。Token认证就是这种方案的一个代表。
2.Token认证
Token 是在服务端产生的一串字符串,是客户端访问资源接口(API)时所需要的资源凭证。
2.1 认证过程
用户----发送用户名和密码—>服务器
服务器---- 验证通过后,签发一个token ----->用户: 存储起来(cookie/localStorage)
用户----发送请求,传回token–>服务器
服务器 -----解析token,查询到用户信息,返回user----> 用户
2.2 特点
服务端no数据:基于 token 的用户认证是一种服务端无状态的认证方式,服务端不用存放 token 数据。
时间换空间:用解析 token 的计算时间换取 session 的存储空间,从而减轻服务器的压力,减少频繁的查询数据库
token 完全由应用管理,所以它可以避开同源策略
3. JWT实现token认证
3.1 JWT组成
- Header(头部):描述 JWT 的元数据
- (alg:签名算法;type:JWT)
- Payload(负载):存放实际需要传递的数据
- issuer(签发人)、expiration(过期时间)、subject(主题)、audience(受众)、Not Before(生效时间)、issued At(签发时间)、JWTID(编号)
- Signature(签名):对前两部分的签名,防止数据篡改
- 指定secret(密钥),安装头部的签名算法将密钥生成签名。
3.2 使用流程
step1:加入依赖
<!--JWT认证-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
step2:封装成JwtUtils工具类
public class JwtUtils {
//7天过期(自定义)
private static long expire = 604800;
//32位秘钥(自定义)
private static String secret = "asdfghjklzxcvbnmlkjhgfdsazxcvbnm";
//生成token
public static String generateToken(String subject){
//....
}
//解析token
public static Claims getClaimsByToken(String token){
// ....
}
//....
}
生成token
//生成token
public static String generateToken(String subject){
Date now = new Date();
Date expiration = new Date(now.getTime() + 1000 * expire);
return Jwts.builder()
.setHeaderParam("type","JWT")
.setSubject(subject)
.setIssuedAt(now)
.setExpiration(expiration)
.signWith(SignatureAlgorithm.HS256,secret)
.compact();
}
解析token
//解析token
public static Claims getClaimsByToken(String token){
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
}
//解析token获取其subject
public static String getSubjectByToken(String token){
return JwtUtils.getClaimsByToken(token).getSubject();
}
step3:使用JwtUtils进行token认证
登录认证
//jwt登录认证
@RequestMapping("login")
public JsonResult<String> login(int id, String password){
//认证密码正确与否
User user = service.login(id, password);
//获取token
String token = JwtUtils.generateToken(user.getId().toString());
//返回token
return new JsonResult<String>(OK,token);
}
获取信息
//获取用户信息
@RequestMapping("getUser")
public JsonResult<User> getUser(String token){
//解析token获取用户id
String subject = JwtUtils.getSubjectByToken(token);
//根据id获取数据库的user信息
User user = service.getById(userId);
return new JsonResult<User>(OK,user);
}