JWT介绍
JWT:
-
JSON Web Token,json格式的web令牌技术,属于令牌技术的一种。用于解决web开发中的身份识别问题
-
定义了一种简洁的、自包含的格式,用于在通信双方以json数据格式传输信息。由于数字签名的存在,这些信息是可靠的。
JWT的特性:
-
可以防篡改。一旦被篡改,服务端可以校验出来的
-
不能防泄露。任何人得到jwt令牌,都可以从中得到 令牌承载的用户信息
JWT的注意:
-
生成token时,一定不要往token里放敏感信息。比如用户的密码、手机号等等
JWT结构
由三部分组成 :
-
Header头:里边放的是令牌的类型、签名算法等等元数据信息。使用Base64Url编码得到的
-
Body载荷:里边放的是用户的身份信息。使用Base64Url编码得到的
-
Signature签名:Header + Body + 密钥字符串,通过签名算法生成签名,用于做防篡改校验
业务场景
用户在登录后对其它功能的访问中,服务端并不知道当是哪个用户帐号在做本次操作,这是不利于系统的权限控制的。
如果想要服务端能够识别每次请求的用户身份,就需要在登录成功后的每次请求中,共享当前用户的身份数据
JWT示例
添加依赖
<!--JWT-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
添加JWT工具类
一般放在util工具包下
public class JwtUtils {
private static final String SIGN_KEY = "pupu";
private static final Long EXPIRE = 43200000L;
/**
* 生成JWT令牌
* @param claims JWT第二部分负载 payload 中存储的内容
* @return
*/
public static String generateJwt(Map<String, Object> claims){
String jwt = Jwts.builder()
.addClaims(claims)
.signWith(SignatureAlgorithm.HS256, SIGN_KEY)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
.compact();
return jwt;
}
/**
* 解析JWT令牌
* @param jwt JWT令牌
* @return JWT第二部分负载 payload 中存储的内容
*/
public static Claims parseJWT(String jwt){
Claims claims = Jwts.parser()
.setSigningKey(SIGN_KEY)
.parseClaimsJws(jwt)
.getBody();
return claims;
}
}
登录功能实现(JWT)
controller层
@RestController
public class LoginController {
@Autowired
private EmpService empService;
@PostMapping("/login")
public Result login(@RequestBody Emp emp) {
Emp e = empService.login(emp);
if (e != null) {
Map<String, Object> claims = new HashMap<>();
claims.put("id", e.getId());
claims.put("username", e.getUsername());
String token = JwtUtils.generateJwt(claims);
return Result.success(token);
}
return Result.error("帐号或密码错误");
}
}
service层
public interface EmpService {
Emp login(Emp emp);
}
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
@Override
public Emp login(Emp emp) {
return empMapper.login(emp);
}
}
dao层
@Mapper
public interface EmpMapper {
@Select("select * from emp where username = #{username} and password = #{password}")
Emp login(Emp emp);
}
实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {
private Integer id; //ID
private String username; //用户名
private String password; //密码
private String name; //姓名
private Short gender; //性别 , 1 男, 2 女
private String image; //图像url
private Short job; //职位
//设置时区
@JsonFormat(timezone = "GMT+8")
private LocalDate entrydate; //入职日期
private Integer deptId; //部门ID
private LocalDateTime createTime; //创建时间
private LocalDateTime updateTime; //修改时间
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
private Integer code;//响应码,1 代表成功; 0 代表失败
private String msg; //响应信息 描述字符串
private Object data; //返回的数据
//增删改 成功响应
public static Result success(){
return new Result(1,"success",null);
}
//查询 成功响应
public static Result success(Object data){
return new Result(1,"success",data);
}
//失败响应
public static Result error(String msg){
return new Result(0,msg,null);
}
}
JWT总结
JWT的使用:
-
客户端提交帐号密码进行登录
服务端校验帐号和密码
如果帐号密码正确,就给用户生成一个token,返回给客户端
-
客户端得到token以后,后续每次请求都要携带token到服务端
服务端接收token,校验token是否被篡改
如果没有被篡改,就解析token得到用户的身份信息