利用jwt生成token,用于http请求身份验证
前段时间在做移动端接口过程中,考虑到安全性,所有移动端发送请求(除了登录请求)过程中进行token有效验证。
1.利用jwt生成token
a.导入jwt相关包
<!-- jwt --> <dependency> <groupId>com.nimbusds</groupId> <artifactId>nimbus-jose-jwt</artifactId> <version>4.23</version> </dependency>
b.编写生成token的工具类TokenUtils
public class TokenUtils { private static final byte[] secret = "geiwodiangasfdjsikolkjikolkijswe".getBytes(); //生成一个token public static String creatToken(String uid) throws JOSEException { Map<String,Object> payloadMap = new HashMap<>(); payloadMap.put("uid", uid); //生成时间 payloadMap.put("sta", new Date().getTime()); //过期时间 payloadMap.put("exp", new Date().getTime()+1000*60*60*24); //24小时token失效 //先建立一个头部Header JWSHeader jwsHeader = new JWSHeader(JWSAlgorithm.HS256); //建立一个载荷Payload Payload payload = new Payload(new JSONObject(payloadMap)); //将头部和载荷结合在一起 JWSObject jwsObject = new JWSObject(jwsHeader, payload); //建立一个密匙 JWSSigner jwsSigner = new MACSigner(secret); //签名 jwsObject.sign(jwsSigner); //生成token return jwsObject.serialize(); } public static Map<String,Object> valid(String token) throws JOSEException, ParseException { JWSObject jwsObject = JWSObject.parse(token); //获取到载荷 Payload payload=jwsObject.getPayload(); //建立一个解锁密匙 JWSVerifier jwsVerifier = new MACVerifier(secret); Map<String, Object> resultMap = new HashMap<>(); //判断token if (jwsObject.verify(jwsVerifier)) { resultMap.put("Result", 0); //载荷的数据解析成json对象。 JSONObject jsonObject = payload.toJSONObject(); resultMap.put("data", jsonObject); //判断token是否过期 if (jsonObject.containsKey("exp")) { Long expTime = Long.valueOf(jsonObject.get("exp").toString()); Long nowTime = new Date().getTime(); //判断是否过期 if (nowTime > expTime) { //已经过期 resultMap.clear(); resultMap.put("Result", 2); } } }else { resultMap.put("Result", 1); } return resultMap; } }
2.对于移动端所有请求进行过滤
a.在web.xml中配置相关过滤器(对所有请求含有/app开头的进行拦截,除了/app/login)
<filter> <filter-name>AppRequestFilter</filter-name> <filter-class>com.demo.common.filter.AppRequestFilter</filter-class> <init-param> <param-name>excludedRequests</param-name> <param-value>/app/login</param-value> </init-param> </filter> <filter-mapping> <filter-name>AppRequestFilter</filter-name> <url-pattern>/app/*</url-pattern> </filter-mapping>
b.编写AppRequestFilter类
public class AppRequestFilter implements Filter{ private String excludedRequests; private String[] excludedRequestArr; @Override public void init(FilterConfig filterConfig) throws ServletException { excludedRequests = filterConfig.getInitParameter("excludedRequests"); if(excludedRequests != null && excludedRequests.length() > 0){ excludedRequestArr = excludedRequests.split(","); } return; } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; boolean isExcludedRequest = false; for (String requestStr : excludedRequestArr) { if (((HttpServletRequest) request).getServletPath().startsWith(requestStr)) { isExcludedRequest = true; break; } } if(isExcludedRequest){ chain.doFilter(request, response); }else{ String token = req.getHeader("app_token"); if(StringUtil.isEmpty(token)){ responseError(res, "token为空!"); return; }else{ Map<String, Object> validMap; try { validMap = TokenUtils.valid(token); int i = (int) validMap.get("Result"); if (i == 0) { chain.doFilter(request, response); } else if (i == 2) { responseError(res, "token已经过期!"); return; } else if(i == 1) { responseError(res, "token无效!"); return; } } catch (JOSEException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } } } } @SuppressWarnings("deprecation") private void responseError(HttpServletResponse res, String errorMsg) throws IOException { res.setHeader("content-type", "application/json;charset=UTF-8"); OutputStream outputStream = res.getOutputStream(); JsonResult msg = new JsonResult(false, errorMsg); IOUtils.write(JSONUtil.toJsonPrettyStr(msg), outputStream); } @Override public void destroy() { return; } }
3.测试类编写
@Controller @RequestMapping(value = "/app") public class AppLogin { @RequestMapping(value = "/login") @ResponseBody public String login(String loginCode, String password){ String token = ""; try { token = TokenUtils.creatToken(loginCode); } catch (JOSEException e) { e.printStackTrace(); } return token; } }
@Controller @RequestMapping(value = "/app/user") public class AppSysUserController { @RequestMapping(value = "/getLoginName") @ResponseBody public String getLoginName(){ return "admin"; } }
4.调用查看结果