diff --git a/pom.xml b/pom.xml index 4861124..252bb63 100644 --- a/pom.xml +++ b/pom.xml @@ -93,11 +93,18 @@ + + + + + + - io.jsonwebtoken - jjwt - 0.9.1 + com.auth0 + java-jwt + 3.8.3 + diff --git a/src/main/java/cn/chjyj/szwh/Interceptor/ChInterceptor.java b/src/main/java/cn/chjyj/szwh/Interceptor/ChInterceptor.java index 5a7b73a..c6aa62f 100644 --- a/src/main/java/cn/chjyj/szwh/Interceptor/ChInterceptor.java +++ b/src/main/java/cn/chjyj/szwh/Interceptor/ChInterceptor.java @@ -1,14 +1,18 @@ package cn.chjyj.szwh.Interceptor; +import cn.chjyj.szwh.annotation.PassToken; import cn.chjyj.szwh.exception.ChException; +import cn.chjyj.szwh.utils.JwtUtils; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Method; @Component public class ChInterceptor implements HandlerInterceptor { @@ -16,42 +20,56 @@ public class ChInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - //输出头 - setHeader(response,request); - //如果非login页面,则判断header 中是否有 chtoken - String url=request.getRequestURI().trim(); - if(!url.contains("/login")){ - String chtoken = request.getHeader("chtoken"); - if(StringUtils.isEmpty(chtoken)){ - throw new ChException("token记录不存在,请确认是否已经登录成功"); + // 从请求头中获取token + String token = request.getHeader("token"); + // 如果不是映射到方法直接通过 + if(!(handler instanceof HandlerMethod)){ + return true; + } + HandlerMethod handlerMethod = (HandlerMethod) handler; + Method method = handlerMethod.getMethod(); + //检查是否有passtoken注释,有则跳过认证 + if (method.isAnnotationPresent(PassToken.class)) { + PassToken passToken = method.getAnnotation(PassToken.class); + if (passToken.required()) { + return true; } - //String token = request.getParameter("token"); -// if(StringUtils.isBlank(token)){ -// throw new ChException("token没有传入,禁止使用"); -// } - //调用验证 -// if(rsaService.chkToken(token)){ -// return true; + } + //默认全部检查 + else { + // 执行认证 + if (token == null) { + throw new ChException("请登录重试"); + } + + // 获取 token 中的 user Name + String userId = JwtUtils.getAudience(token); + + //找找看是否有这个user 因为我们需要检查用户是否存在,读者可以自行修改逻辑 + // todo +// AccountDTO user = accountService.getByUserName(userId); +// +// if (user == null) { +// //这个错误也是我自定义的 +// throw new ChException("用户不存在"); // } + + // 验证 token + JwtUtils.verifyToken(token, userId); + + //获取载荷内容 + String userName = JwtUtils.getClaimByName(token, "userName").asString(); + String realName = JwtUtils.getClaimByName(token, "realName").asString(); + + //放入attribute以便后面调用 + request.setAttribute("userName", userName); + request.setAttribute("realName", realName); + + return true; } - return false; + return true; } - /** - * 设置输出头,添加跨域 - * @param response - */ - private void setHeader(HttpServletResponse response,HttpServletRequest request){ - //跨域的header设置 - response.setHeader("Access-control-Allow-Origin", request.getHeader("Origin")); - response.setHeader("Access-Control-Allow-Methods", request.getMethod()); - response.setHeader("Access-Control-Allow-Credentials", "true"); - response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers")); - // 个性化主机设置 - response.setHeader("chhong","true"); - // 防止乱码 - response.setHeader("Content-Type","application/json;charset=UTF-8"); - } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { diff --git a/src/main/java/cn/chjyj/szwh/utils/JwtUtils.java b/src/main/java/cn/chjyj/szwh/utils/JwtUtils.java index c20233a..a465d8a 100644 --- a/src/main/java/cn/chjyj/szwh/utils/JwtUtils.java +++ b/src/main/java/cn/chjyj/szwh/utils/JwtUtils.java @@ -1,212 +1,79 @@ package cn.chjyj.szwh.utils; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.CompressionCodecs; -import io.jsonwebtoken.JwtBuilder; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; - +import cn.chjyj.szwh.exception.ChException; +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTDecodeException; +import com.auth0.jwt.interfaces.Claim; +import com.auth0.jwt.interfaces.DecodedJWT; + +import java.util.Calendar; import java.util.Date; /** * jwt工具类 */ public class JwtUtils { - /** - * 实例 - */ - private static JwtUtils instance; - - /** - * 发行者 - */ - private String subObject = "owner"; /** - * 过期时间,默认7天 + * 签发对象:这个用户的id + * 签发时间:现在 + * 有效时间:30分钟 + * 载荷内容:暂时设计为:这个人的名字,这个人的昵称 + * 加密密钥:这个人的id加上一串字符串 */ - private long expired = 1000 * 60 * 60 * 24 * 7; - - /** - * jwt构造 - */ - private static JwtBuilder jwtBuilder; - - /** - * 密钥 - */ - private String secret = "secret";// 密钥 - - /** - * 获取实例 - * @return - */ - public static JwtUtils getInstance(){ - if (instance == null){ - instance = new JwtUtils(); - } - jwtBuilder = Jwts.builder(); - return instance; + public static String createToken(String userId, String realName, String userName) { + + Calendar nowTime = Calendar.getInstance(); + nowTime.add(Calendar.MINUTE, 30); + Date expiresDate = nowTime.getTime(); + + return JWT.create().withAudience(userId) //签发对象 + .withIssuedAt(new Date()) //发行时间 + .withExpiresAt(expiresDate) //有效时间 + .withClaim("userName", userName) //载荷,随便写几个都可以 + .withClaim("realName", realName) + .sign(Algorithm.HMAC256(userId + "HelloLehr")); //加密 } /** - * 荷载信息(通常是一个User信息,还包括一些其他的元数据) - * @param key - * @param val - * @return - */ - public JwtUtils setClaim(String key,Object val){ - jwtBuilder.claim(key,val); - return this; - } - - /** - * 生成 jwt token - * @return - */ - public String generateToken(){ - String token = jwtBuilder - .setSubject(subObject) // 发行者 - //.claim("id","121") // 参数 - .setIssuedAt(new Date()) // 发行时间 - .setExpiration(new Date(System.currentTimeMillis() + expired)) - .signWith(SignatureAlgorithm.HS256,secret) // 签名类型 与 密钥 - .compressWith(CompressionCodecs.DEFLATE)// 对载荷进行压缩 - .compact(); // 压缩一下 - return token; - } - - /** - * 解析 token + * 检验合法性,其中secret参数就应该传入的是用户的id + * * @param token - * @return - */ - public Claims check(String token){ - try{ - final Claims claims = Jwts.parser() - .setSigningKey(secret) - .parseClaimsJws(token) - .getBody(); - return claims; - }catch (Exception e){} - return null; - } - - public String getSubObject() { - return subObject; - } - - /** - * 设置发行者 - * @param subObject - * @return */ - public JwtUtils setSubObject(String subObject) { - this.subObject = subObject; - return this; - } - - public long getExpired() { - return expired; + public static void verifyToken(String token, String secret) { + DecodedJWT jwt = null; + try { + JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret + "HelloLehr")).build(); + jwt = verifier.verify(token); + } catch (Exception e) { + //效验失败 + //这里抛出的异常是我自定义的一个异常,你也可以写成别的 + throw new ChException("token验证失败"); + } } /** - * 设置过期时间 - * @param expired - * @return + * 获取签发对象 */ - public JwtUtils setExpired(long expired) { - this.expired = expired; - return this; + public static String getAudience(String token) { + String audience = null; + try { + audience = JWT.decode(token).getAudience().get(0); + } catch (JWTDecodeException j) { + //这里是token解析失败 + throw new ChException("token解析失败"); + } + return audience; } - public String getSecret() { - return secret; - } /** - * 设置密钥 - * @param secret - * @return + * 通过载荷名字获取载荷的值 */ - public JwtUtils setSecret(String secret) { - this.secret = secret; - return this; + public static Claim getClaimByName(String token, String name) { + return JWT.decode(token).getClaim(name); } } - -// import com.auth0.jwt.JWT; -// import com.auth0.jwt.JWTVerifier; -// import com.auth0.jwt.algorithms.Algorithm; -// import com.auth0.jwt.exceptions.JWTDecodeException; -// import com.auth0.jwt.interfaces.Claim; -// import com.auth0.jwt.interfaces.DecodedJWT; -// -// import java.io.Serializable; -// import java.util.Calendar; -// import java.util.Date; -// - -//public class JwtUtils { -// -// /** -// 签发对象:这个用户的id -// 签发时间:现在 -// 有效时间:30分钟 -// 载荷内容:暂时设计为:这个人的名字,这个人的昵称 -// 加密密钥:这个人的id加上一串字符串 -// */ -// public static String createToken(String userId,String realName, String userName) { -// -// Calendar nowTime = Calendar.getInstance(); -// nowTime.add(Calendar.MINUTE,30); -// Date expiresDate = nowTime.getTime(); -// -// return JWT.create().withAudience(userId) //签发对象 -// .withIssuedAt(new Date()) //发行时间 -// .withExpiresAt(expiresDate) //有效时间 -// .withClaim("userName", userName) //载荷,随便写几个都可以 -// .withClaim("realName", realName) -// .sign(Algorithm.HMAC256(userId+"HelloLehr")); //加密 -// } -// -// /** -// * 检验合法性,其中secret参数就应该传入的是用户的id -// * @param token -// * @throws TokenUnavailable -// */ -// public static void verifyToken(String token, String secret) throws TokenUnavailable { -// DecodedJWT jwt = null; -// try { -// JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret+"HelloLehr")).build(); -// jwt = verifier.verify(token); -// } catch (Exception e) { -// //效验失败 -// //这里抛出的异常是我自定义的一个异常,你也可以写成别的 -// throw new TokenUnavailable(); -// } -// } -// -// /** -// * 获取签发对象 -// */ -// public static String getAudience(String token) throws TokenUnavailable { -// String audience = null; -// try { -// audience = JWT.decode(token).getAudience().get(0); -// } catch (JWTDecodeException j) { -// //这里是token解析失败 -// throw new TokenUnavailable(); -// } -// return audience; -// } -// -// -// /** -// * 通过载荷名字获取载荷的值 -// */ -// public static Claim getClaimByName(String token, String name){ -// return JWT.decode(token).getClaim(name); -// } -//} diff --git a/szwh.iml b/szwh.iml index 4f0dcb3..62dda43 100644 --- a/szwh.iml +++ b/szwh.iml @@ -102,7 +102,7 @@ - +