- JWT是用于微服务之间传递用户信息的一段加密字符串,该字符串是一个JSON格式,各个微服务可以根据该JSON字符串识别用户的身份信息,这个JSON字符串可以封装用户的身份信息
- JWT的构成
- 头部(Header)
- 头部用于描述JWT的基本信息,指定了令牌类型和加密算法
- 载荷(Payload)
- 载荷是存放有效信息的地方
- 标准注册中的声明
- iss: jwt签发者
- sub: 当前令牌的描述说明
- aud: 接收jwt的一方
- exp: jwt的过期时间,过期时间必须大于签发时间
- nbf: 定义在什么时间之前,该jwt都是不能使用的
- iat: jwt的签发时间
- jti: jwt的唯一身份标识
- 公共的声明
- 公共的声明可以添加任何信息,一般添加用户的相关信息或其他业务的必要信息,不建议添加敏感信息,因为该部分在客户端可解密
- 私有的声明
- 私有声明是提供者和消费者所共同定义的声明,不建议存放敏感的信息
- 标准注册中的声明
- 载荷是存放有效信息的地方
- 签名
- jwt的第三部分是一个签证信息,用于校验令牌是否被修改
- 签名信息由以下三个部分组成
- Header(base64后的)
- Payload(base64后的)
- Secret(秘钥)
- 签名的组成
- 头部信息base64 + 载荷base64 + Header中声明的加密方式进行加盐Secret组合加密,从而构成第三部分,也就是所谓的签名
- 头部(Header)
1.创建数据库,建立user_info表,用于用户认证数据
-- 创建数据库 create DATAbase if not exists jwt_test; -- 使用当前创建的数据库 use jwt_test; -- 创建表 create table user_info ( id int primary key auto_increment, age int, username varchar(20), password varchar(15), address varchar(255) ); -- 插入数据 insert into user_info(age,username,password,address) values (18,'zhangsan','123456','SZ');
2.创建springboot工程,pom依赖如下
org.springframework.boot spring-boot-starter-parent2.1.4.RELEASE 8 8 org.springframework.boot spring-boot-starter-weborg.springframework.boot spring-boot-starter-testtest org.mybatis.spring.boot mybatis-spring-boot-starter2.2.0 com.auth0 java-jwt3.18.2 mysql mysql-connector-java8.0.25 org.projectlombok lombokcom.google.code.gson gson
3.创建application.yaml文件,添加mybatis配置信息
server:
port: 8080
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/jwt_test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username: root
password: 123456
#配置mybatis的mapper映射文件位置
mybatis:
mapper-locations: classpath:mappers
UserInfo findByUsernameAndPassword(String username, String password);
UserInfo findUserInfoById(Integer id);
}
7.在resources目录下创建mappers目录,并创建对应的UserInfoDao.xml文件
8.创建对应的service层
//service接口
public interface UserInfoService {
UserInfo findByUsernameAndPassword(String username, String password);
UserInfo findUserInfoById(Integer id);
}
//service实现类
@Service
public class UserInfoServiceImpl implements UserInfoService {
@Autowired
private UserInfoDao userInfoDao;
@Override
public UserInfo findByUsernameAndPassword(String username, String password) {
return userInfoDao.findByUsernameAndPassword(username, password);
}
@Override
public UserInfo findUserInfoById(Integer id) {
return userInfoDao.findUserInfoById(id);
}
}
9.创建对应的controller层
@RestController
public class UserInfoController {
@Autowired
private UserInfoService userInfoService;
@PostMapping("/user/login")
public Map login(@RequestBody UserInfo userInfo) {
UserInfo user = userInfoService.findByUsernameAndPassword(userInfo.getUsername(), userInfo.getPassword());
Map map = new HashMap<>();
if (user != null) {
Map payload = new HashMap<>();
payload.put("userId", user.getId() + "");
payload.put("username", user.getUsername());
String token = JwtUtil.generateToken(payload);
map.put("status", "OK");
map.put("token", token);
return map;
}
map.put("status", "failed");
return map;
}
@GetMapping("/user/info/id/{id}")
public UserInfo getUserInfoById(@PathVariable(value = "id") Integer id) {
return userInfoService.findUserInfoById(id);
}
}
10.创建JwtUtil.java
public class JwtUtil {
private static final String SECRET = "CCMetric";
public static String generateToken(Map payload) {
Calendar instance = Calendar.getInstance();
instance.add(Calendar.DATE, 1);
JWTCreator.Builder builder = JWT.create();
//载荷,生成token中保存的信息
payload.forEach(builder::withClaim);
return builder.withAudience("admin") //签发对象
.withIssuedAt(new Date()) //发行时间
.withExpiresAt(instance.getTime()) //过期时间
.sign(Algorithm.HMAC256(SECRET)); //加密算法+盐
}
public static DecodedJWT verify(String token) {
return JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);
}
public static Map getPayloadByToken(String token) {
return verify(token).getClaims();
}
}
11.创建拦截器JwtInterceptor
public class JwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("Authorization");
Map map = new HashMap<>();
if (token != null) {
try {
JwtUtil.verify(token);
return true;
} catch (Exception e) {
map.put("msg", "token无效");
}
} else {
map.put("msg", "token为空");
}
map.put("status", false);
//错误信息响应到前台
response.setContentType("application/json;charset=utf-8");
response.getWriter().print(new Gson().toJson(map));
response.setStatus(HttpStatus.FORBIDDEN.value());
return false;
}
}
12.将拦截器JwtInterceptor添加配置
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JwtInterceptor())
.addPathPatterns("/**") //拦截路径
.excludePathPatterns("/user/login"); //登录接口排除
}
}
13.接口测试
登录测试,返回token
获取用户信息,提供伪造token
获取用于信息,提供正确token



