Token的使用
springboot+vue实现前后端分离中token的使用
1.Token的使用
客户端使用用户名跟密码请求登录
服务端收到请求,去验证用户名与密码
验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据
APP登录的时候发送加密的用户名和密码到服务器,服务器验证用户名和密码,如果成功,以某种方式比如随机生成32位的字符串作为token,存储到服务器中,并返回token到APP,以后APP请求时
凡是需要验证的地方都要带上该token,然后服务器端验证token,成功返回所需要的结果,失败返回错误信息,让他重新登录。其中服务器上token设置一个有效期,每次APP请求的时候都验证token和有效期
Token 都需要设有效期。根据系统的安全需要,尽可能的短
2.使用JWT生成并校验Token
2.1.JWT简介
通俗地说,JWT的本质就是一个字符串**,它是将用户信息保存到一个Json字符串中,然后进行编码后得到一个
JWT token
,**并且这个JWT token
带有签名信息,接收后可以校验是否被篡改,所以可以用于在各方之间安全地将信息作为Json对象传输。
2.2 .JWT的结构
JWT由3部分组成:标头(Header)、有效载荷(Payload)和签名(Signature)。在传输的时候,会将JWT的3部分分别进行Base64编码后用
.
进行连接形成最终传输的字符串
3.使用JWT
3.1引入依赖
<!-- JWT -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>
3.2.创建TokenUtils,用于生成Token
public static String getToken(User user){
String token = JWT.create().withAudience(user.getId().toString())//基于JWT创建Token并将user的id存在Token
.withExpiresAt(DateUtil.offsetHour(new Date(),2))//两个小时以后Token过期
.sign(Algorithm.HMAC256(user.getPassword()));//以password作为token的密钥
return token;
}
3.3.User实体类添加Token字段,用于登录用户携带token
给实体类添加上反馈前端的字段token
@TableField(exist = false)//只为了前端和后端的验证,该字段不加在数据库表里面
private String token;
登录的方法里面从前面编写的TokenUtils中获取生成的token,存储到返回前端的user里面
//userService登录的时候携带token存到user对象
public User login(User loginUser) {
// TODO Auto-generated method stub
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username", loginUser.getUsername()).eq("password", loginUser.getPassword());
List<User> list = userMapper.selectList(queryWrapper);
if(list.size()==0) {
return null;
}
else {
User user = list.get(0);
String token = TokenUtils.getToken(user);
user.setToken(token);
return user;
}
}
3.4.前端拿到token,设置请求后端时候请求头携带token
// request 拦截器
// 可以自请求发送前对请求做一些处理
// 比如统一加token,对请求参数统一加密
request.interceptors.request.use(config => {
config.headers['Content-Type'] = 'application/json;charset=utf-8';
const user = SessionStorage.get("user");
if(user){
config.headers['token'] = user.token;
}
return config
}, error => {
return Promise.reject(error)
});
3.5.后端创建JWT拦截器,验证token
@Autowired
private UserService userService;
/**
* 拦截器的前置方法,返回true代表放行
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取请求头中的token
String token = request.getHeader("token");
//如果请求的不是处理器的方法直接通过,(拦截controller)
if(!(handler instanceof HandlerMethod)){
return true;
}
//如果token为空白字符串,则抛出异常(判断token是否存在)CustomException是自定义异常类
if(StrUtil.isBlank(token)){
throw new CustomException(401,"无token,请重新登录");
}
//获取token中的id
String strUserId;
try {
strUserId = JWT.decode(token).getAudience().get(0);
}catch (Exception e){
throw new CustomException(401,"token验证失败,请重新登录");
}
//从token获取id后查询
User user = userService.getById(Integer.parseInt(strUserId));
if (user==null) {
throw new CustomException(401, "用户不存在,请重新登录");
}
// 用户密码加密验证
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
try {
jwtVerifier.verify(token);
}catch (Exception e){
throw new CustomException(401, "token验证失败,请重新登录");
}
//如果以上代码都没有发生异常则放行
return true;
}
3.6.配置JWT拦截器的配置类,设置拦截规则和放行规则
@Override
public void addInterceptors(InterceptorRegistry registry) {
//添加自定义的拦截器JWTInterceptor
registry.addInterceptor(this.jwtInterceptor())
.addPathPatterns("/**")// 拦截所有请求
.excludePathPatterns(" /user/login", " /file/**", "/**/importExl", "/*/export");
}
//将jwt拦截器对象交给spring管理
@Bean
public JWTInterceptor jwtInterceptor() {
return new JWTInterceptor();
}
更多推荐
所有评论(0)