JWT初步使用以及页面刷新就显示JWT过期的问题

JWT配置

HTTPResponse.java

package xyz.nieqiang.webapp.util;

public class HTTPResponse {
	private Integer status;
	private String message;
	private Object data;
	
	public static HTTPResponse ok(String message) {
		return new HTTPResponse(200, message);
	}
	
	public static HTTPResponse ok(Object data) {
		return new HTTPResponse(200, data);
	}
	
	public static HTTPResponse ok(String message,Object data) {
		return new HTTPResponse(200, message, data);
	}
	
	public static HTTPResponse error(Integer status, String message) {
		return new HTTPResponse(500, message, null);
	}
	
	public static HTTPResponse error(String message) {
		return new HTTPResponse(500, message, null);
	}
	
	public static HTTPResponse error(String message,Object data) {
		return new HTTPResponse(500, message, data);
	}
	
	
	protected HTTPResponse() {super();}
	
	private HTTPResponse(Integer status, String message) {
		this.status = status;
		this.message = message;
	}
	
	private HTTPResponse(Integer status, Object data) {
		this.status = status;
		this.data = data;
	}
	
	private HTTPResponse(Integer status, String message, Object data) {
		this.status = status;
		this.message = message;
		this.data = data;
	}
	
	
	public Integer getStatus() {return status;}
	public String getMessage() {return message;}
	public Object getData() {return data;}
	public void setStatus(Integer status) {this.status = status;}
	public void setMessage(String message) {this.message = message;}
	public void setObject(Object data) {this.data = data;}
}

JWTConfiguration.java

package xyz.nieqiang.webapp.configuration;

import java.io.PrintWriter;
import java.util.Date;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import xyz.nieqiang.webapp.util.HTTPResponse;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

@Component
public class JWTConfiguration implements HandlerInterceptor {
	private final static Logger logger = LoggerFactory.getLogger(JWTConfiguration.class);

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

		// 如果cookie不为空
		if (request.getHeader("Cookie") != null) {
			try {
				JwtParser parser = Jwts.parser();
				// 加密盐值
				parser.setSigningKey("liangzhun-@20200805");
				// 解析token
				Cookie[] cookies = request.getCookies();
				String CookieToken = null;
				for (int i = 0; i < cookies.length; i++) {
					if (cookies[i].getName().equals("token")) {
						CookieToken = cookies[i].getValue();
					}
				}
				Jws<Claims> claimsJws = parser.parseClaimsJws(CookieToken);
				// token有效期7天,如果有效期小于3天,置为7天
				if (Integer.parseInt(claimsJws.getBody().get("exp").toString()) - System.currentTimeMillis() / 1000 < 60 * 60 * 24 * 3) {
					logger.info("token续签!!!");

					String token = Jwts.builder().setSubject(claimsJws.getBody().getSubject()).setIssuedAt(new Date())
							.setExpiration(new Date(System.currentTimeMillis() + 29 * 24 * 60 * 60 * 1000))
							.signWith(SignatureAlgorithm.HS256, "liangzhun-@20200805").compact();
					// set cookie到前端
					Cookie cookie = new Cookie("token", token);
					cookie.setPath("/");
					cookie.setMaxAge(60 * 60 * 24 * 10);
					response.addCookie(cookie);
				}
				// 解析成功拦截器放行
				return true;
				// 抛异常token解析失败
			} catch (ExpiredJwtException e) {// token过期
				logger.info("token过期");
				response.setContentType("application/json;charset=UTF-8");
				response.setStatus(401);
				PrintWriter printWriter = response.getWriter();
				HTTPResponse httpResponse = HTTPResponse.error("用户身份过期", 401);
				String s = new ObjectMapper().writeValueAsString(httpResponse);
				printWriter.write(s);
				printWriter.flush();
				printWriter.close();
				return false;
			} catch (Exception e) {
				logger.info("token错误");
				response.setContentType("application/json;charset=UTF-8");
				PrintWriter printWriter = response.getWriter();
				HTTPResponse httpResponse = HTTPResponse.error("用户身份错误", 403);
				String s = new ObjectMapper().writeValueAsString(httpResponse);
				printWriter.write(s);
				printWriter.flush();
				printWriter.close();
				return false;
			}
		} else {
			logger.info("token is null");
			response.setContentType("application/json;charset=UTF-8");
			PrintWriter printWriter = response.getWriter();
			HTTPResponse httpResponse = HTTPResponse.error("token is null", 403);
			String s = new ObjectMapper().writeValueAsString(httpResponse);
			printWriter.write(s);
			printWriter.flush();
			printWriter.close();
			return false;
		}
	}
}

JWTFilterConfig.java

package xyz.nieqiang.webapp.configuration;
import javax.annotation.Resource;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class JWTFilterConfig implements WebMvcConfigurer {
    @Resource
    private JWTConfiguration jWTConfiguration;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jWTConfiguration)
        .addPathPatterns("/**")//拦截所有接口
        .excludePathPatterns("/login");//不拦截/login接口
    }
}

LoginController.java

package xyz.nieqiang.webapp.controller;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import xyz.nieqiang.webapp.entity.User;
import xyz.nieqiang.webapp.util.HTTPResponse;
@RestController
public class LoginController {
	private static final Logger logger = LoggerFactory.getLogger(LoginController.class);
	@PostMapping("/login")
	public HTTPResponse login(String username, String password, HttpServletResponse response) {
		User user = new User();
		user.setId(111);
		user.setUsername("liangzhun");
		user.setPassword("liangzhun@4399");
		logger.info("{}```{}```{}```{}",username,user.getUsername(),password,user.getPassword());
		if(!(user.getUsername().equals(username) && user.getPassword().equals(password))) {
			return HTTPResponse.error("用户名或密码错误!","");
		}
		//存放用户信息
		Map<String, String> map = new HashMap<String , String>();
		map.put("id", user.getId().toString());
		map.put("username", user.getUsername());
		String token = Jwts.builder()
			//存放用户信息
			.setSubject(map.toString())
			//设置当前是时间
			.setIssuedAt(new Date())
			//设置到期时间,7天
			.setExpiration(new Date(System.currentTimeMillis()+7*24*60*60*1000))
			//.setExpiration(new Date(System.currentTimeMillis()-10*24*60*60*1000))
			//加密加盐
            .signWith(SignatureAlgorithm.HS256,"liangzhun-@20200805")
            .compact();;
		//set cookie到前端
		Cookie cookie = new Cookie("token",token);
	    cookie.setPath("/");
	    cookie.setMaxAge(24*60*60*1000*3);
	    response.addCookie(cookie);
	    user.setPassword(null);
		return HTTPResponse.ok("登录成功!");
	}
}

踩坑

坑:页面刷新存在token过期的问题
踩:检查token设置最大时间是否与续签时间长度相冲突,比如设置的最大有效时间为3天,请求时校验token时间不满5天就续签,这里肯定是相冲突的,要改成小于有效时间的天数

你可能感兴趣的:(笔记,Springboot)