使用jwt來創建token和解密token,攔截器則是用來校驗token。
jwt生成token
/**
* @author weiqi:
* @version 創建時間:2018年11月5日 下午9:23:01 登錄Token的生成和解析
*/
public class JwtUtils {
private static Logger log = LoggerFactory.getLogger(JwtUtils.class);
/** token祕鑰,請勿泄露,請勿隨便修改 */
public static final String SECRET = GeneralCode.TOKEN_SECRET;
/** token 過期時間: 10天 */
public static final int calendarField = Calendar.DATE;
public static final int calendarInterval = GeneralCode.TOKEN_OUT_OF_DATE;
/**
* JWT生成Token.<br/>
*
* JWT構成: header, payload, signature
*
* @param user_id
* 登錄成功後用戶user_id, 參數user_id不可傳空
*/
public static String createToken(Long user_id) throws Exception {
log.info("create token...");
Date iatDate = new Date();
// expire time
Calendar nowTime = Calendar.getInstance();
nowTime.add(calendarField, calendarInterval);
Date expiresDate = nowTime.getTime();
// header Map
Map<String, Object> map = new HashMap<>();
map.put("alg", "HS256");
map.put("typ", "JWT");
// build token
// param backups {iss:Service, aud:APP}
String token = JWT.create().withHeader(map) // header
.withClaim("iss", "Service") // payload
.withClaim("aud", "APP").withClaim("user_id", null == user_id ? null : user_id.toString())
.withIssuedAt(iatDate) // sign time
.withExpiresAt(expiresDate) // expire time
.sign(Algorithm.HMAC256(SECRET)); // signature
return token;
}
/**
* 解密Token
*
* @param token
* @return
* @throws Exception
*/
public static Map<String, Claim> verifyToken(String token) throws Exception{
DecodedJWT jwt = null;
log.info("start identify token...");
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
jwt = verifier.verify(token);
return jwt.getClaims();
}
/**
* 根據Token獲取user_id
*
* @param token
* @return user_id
*/
public static Long getUID(String token) throws Exception{
Map<String, Claim> claims = verifyToken(token);
Claim user_id_claim = claims.get("user_id");
if (null == user_id_claim || StringUtils.isEmpty(user_id_claim.asString())) {
return 0L;
}
log.info("get userid " + Long.valueOf(user_id_claim.asString()));
return Long.valueOf(user_id_claim.asString());
}
}
在登錄時創建並給前端返回token
customerRepository.insertLoginInfo(LoginInfoModel);//插入登錄信息
String token = "";
try {
token = JwtUtils.createToken(userid);//生成token
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
customerInfoDto.setCustomerModel(customerModel);
customerInfoDto.setToken(token);
前端調用接口時使用攔截器攔截
public class LoginInterceptor implements HandlerInterceptor {
private static String[] IGNORE_URI = {"/login/login"};
private static Logger log = LoggerFactory.getLogger(HandlerInterceptor.class);
/**
* 進入controller層之前攔截請求
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("---------------------開始進入請求地址攔截----------------------------");
boolean flag = false;
String url = httpServletRequest.getRequestURL().toString();
for (String s : IGNORE_URI) {
if (url.contains(s)) {
flag = true;
break;
}
}
if (!flag) {
String token = httpServletRequest.getHeader("Authorization");
if(!"".equals(token)||!token.isEmpty()) {
try {
JwtUtils.getUID(token);
}catch(Exception e) {
log.error("token失效,當前url:" + url);
e.printStackTrace();
httpServletResponse.setHeader("tokenstatus", "timeout");//在響應頭設置token狀態
httpServletResponse.setCharacterEncoding("text/html;charset=utf-8");
httpServletResponse.setContentType("text/html;charset=utf-8");
httpServletResponse.getWriter().print("this token is time out");
return false;
}
}else {
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("--------------處理請求完成後視圖渲染之前的處理操作---------------");
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("---------------視圖渲染之後的操作-------------------------");
}
}
添加到啓動配置中
@Configuration
public class WebAppConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry){
//註冊自定義攔截器,添加攔截路徑和排除攔截路徑
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/login/**");//攔截除登錄以外的其他接口
}
}
這樣就完成了,每次獲取數據時都需要在請求頭中帶上token,不然就會提示獲取失敗