一、JWT的简单使用
JWT由3部分组成:标头(Header)、有效载荷(Payload)和签名(Signature)。在传输的时候,会将JWT的3部分分别进行Base64编码后用.进行连接形成最终传输的字符串。
JWTString=Base64(Header).Base64(Payload).HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)
第一步,新建一个springboot项目。导入JWT的依赖
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.18.2</version>
</dependency>
第二步,获取令牌
@Test
void contextLoads() {
HashMap<String, Object> map = new HashMap<>();
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND, 60);
String token = JWT.create().withHeader(map)
.withClaim("userId", 1001)
.withClaim("username", "scx")
.withExpiresAt(instance.getTime())
.sign(Algorithm.HMAC256("abcdef"));
System.err.println(token);
}
生成的token
第三步,验证令牌
@Test
void test2() {
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("abcdef")).build();
DecodedJWT verify = jwtVerifier
.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NDE5ODU3OTUsInVzZXJJZCI6MTAwMSwidXNlcm5hbWUiOiJzY3gifQ.UgeZW_5KQlYPRSn05w90WTfscQM5GakULECrJh1M7Sw");
System.err.println(verify.getClaim("userId").asLong());
System.err.println(verify.getClaim("username").asString());
System.err.println("过期时间" + verify.getExpiresAt());
}
如果token没有过期,token没有被修改过就可以验证成功 token过期会抛出异常
token错误也会抛出异常,当然还有其他的异常
二、JWT与springboot的使用(简单模拟web工程)
思路 用户在登录成功的时候,根据id和username(自己根据情况改变)生成一个token。如果用户想要访问登录以后才能访问的模块(比如个人中心)。我们就可以验证用户发送的请求携带的token,如果没有抛出异常,则说明已经登录过了,否则拒绝访问,转到登录页。当然,如果在每个方法里都验证token的合法性会显得代码冗余,我们可以在拦截器统一处理。(token放在请求头中)
包结构
第一步、新建springboot项目。 导入相关的依赖。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.18.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
第二步、创建数据库,创建一张表,插入数据
CREATE DATABASE IF NOT EXISTS JWT
USE JWT
CREATE TABLE IF NOT EXISTS `user`(
id BIGINT,
username VARCHAR(20)
)
INSERT INTO `user` VALUES(1,"scx")
第三步、编写相关的类,在application.proerties下添加配置 3.1首先编写JWT的工具类
public class JWTUtils {
private static final String SIGN = "scxzhenshuai";
public static String createToken(Map<String, String> map) {
Calendar instance = Calendar.getInstance();
instance.add(Calendar.DATE, 7);
JWTCreator.Builder builder = JWT.create();
map.forEach((k, v) -> {
builder.withClaim(k, v);
});
return builder.withExpiresAt(instance.getTime())
.sign(Algorithm.HMAC256(SIGN));
}
public static void checkToken(String token) {
JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);
}
}
3.2 编写实体类
import lombok.Data;
@Data
public class User {
private Long id;
private String username;
}
3.3编写mapper
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.scx.pojo.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
3.4编写service
import com.scx.pojo.User;
import java.util.Map;
public interface UserService {
Map login(User user);
}
3.5编写service的实现类
import java.util.HashMap;
import java.util.Map;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public Map login(User user) {
User userDao = userMapper.selectOne(null);
HashMap<String, String> userMap = new HashMap<>();
HashMap hashMap = new HashMap();
if (userDao == null) {
hashMap.put("state", "登录失败");
return hashMap;
}
hashMap.put("state", "登录成功");
userMap.put("id", userDao.getId().toString());
userMap.put("username", userDao.getUsername());
String token = JWTUtils.createToken(userMap);
hashMap.put("token", token);
return hashMap;
}
}
3.6编写controller
@RestController
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/user/login")
public Map userLogin(User user) {
Map map = userService.login(user);
return map;
}
@PostMapping("/user/info")
public Map info() {
HashMap<Object, Object> map = new HashMap<>();
map.put("state", "访问成功");
return map;
}
}
3.7编写拦截器
public class JWTInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("token");
HashMap<Object, Object> map = new HashMap<>();
try {
JWTUtils.checkToken(token);
return true;
} catch (Exception e) {
map.put("state", "token失效");
ObjectMapper objectMapper = new ObjectMapper();
String s = objectMapper.writeValueAsString(map);
response.setContentType("application/json; charset=UTF-8");
response.getWriter().write(s);
}
return false;
}
}
3.8编写配置类
@Configuration
public class JWTConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JWTInterceptor()).addPathPatterns("/user/info");
}
}
3.9启动项目,测试 我们在postman中发送一个登录的请求 localhost:8081/user/login 登录成功以后会得到一个token 现在以post请求localhost:8081/user/info。没有携带token。访问失败 把token放在header中访问
|