发表于: 2021-04-12 23:24:57

3 1240


今天完成的事情:

图片迁移

修改登录,注册,将密码加密的问题

梳理token的逻辑

完善代码,将Sys.out.println修改成  logger.info



明天计划的事情:

继续了解spring RMI

它可以做什么,解决了什么问题,为什么要用到它,有什么好处



遇到的问题:

1.无法读取Object内容的输入值,系统找不到指定路径

* 图片迁移
* TODO: 代码逻辑:遍历获取阿里云的文件名,将阿里云上的文件转到本地,最后在上传到腾讯云
* FIXME:这里图片迁移的逻辑有问题。
* 1.代码是创建一个父目录,但是没有创建文件。所以它会显示在本地找不到文件。
* 2.获取key的时候,它一开始直接获取image/  文件夹,并不会获取到详细的文件
* FIXME:目前解决办法:在本地创建文件,获取文件的绝对位置。然后把本地文件当作一个中转地。把获取key(文件名)注释
* FIXME:进一步优化的方法:
* 1.先把阿里云图片全部下载到本地,然后在从本地上传的腾讯云
* 2.想到能不能把redis当作中转站
* 3.师兄提供的办法是,看sdk能不能支持云文件





收获:


JWT 工具类

/**
* 生成jwt的方法
* @param date 签发时间
* @param secrety 私钥
* @param
* @return
*/
public static String getJWT(String id, String userName, Date date, String secrety){

JwtBuilder jwtBuilder= Jwts.builder().setId(id).setIssuer(userName)
.setIssuedAt(date)
.signWith(SignatureAlgorithm.HS256,secrety);
   String token = jwtBuilder.compact();
   return token;
}

/**
* 解析token
* @param token token
* @param secrety 私钥
* @return
*/
public static Claims parseJWT(String token, String secrety){
Claims claims=Jwts.parser().setSigningKey(secrety).parseClaimsJws(token).getBody();
   return claims;
}


拦截器验证token:

//从请求中获取cookie, 判断当前用户是否已经登陆
Cookie cookie = CookieUtil.getCookie(request.getCookies(), "token");
//判断客户端是否有cookie
if (cookie != null) {
//cookie得到token
   String value = URLDecoder.decode(cookie.getValue(), "utf-8");
   logger.info("从客户端得到的taken" + value);
   //解密token
   Claims token = JWTUtil.parseJWT(value, SECRE);
   logger.info("解密的taken" + token);
   if(token!=null){
return true;
   }else {
return false;
   }
} else {
String headertoken = request.getHeader("token");
   logger.info("从客户端得到的taken" + headertoken);
   //解密token
   Claims token = JWTUtil.parseJWT(headertoken, SECRE);
   if (token != null){
return true;
   }else {
logger.info("用户没有登录");
       //如果没有检测到登录状态就重定向到登录界面
       response.sendRedirect(request.getContextPath() + "/login");
       return false;
   }
}


对比网上的逻辑:

public class JwtTokenUtil {

private static Logger log = LoggerFactory.getLogger(JwtTokenUtil.class);

   public static final String AUTH_HEADER_KEY = "Authorization";

   public static final String TOKEN_PREFIX = "Bearer ";

   /**
    * 解析jwt
    * @param jsonWebToken
    * @param base64Security
    * @return
    */
   public static Claims parseJWT(String jsonWebToken, String base64Security) {
try {
Claims claims = Jwts.parser()
.setSigningKey(DatatypeConverter.parseBase64Binary(base64Security))
.parseClaimsJws(jsonWebToken).getBody();
           return claims;
       } catch (ExpiredJwtException eje) {
log.error("===== Token过期 =====", eje);
           throw new CustomException(ResultCode.PERMISSION_TOKEN_EXPIRED);
       } catch (Exception e){
log.error("===== token解析异常 =====", e);
           throw new CustomException(ResultCode.PERMISSION_TOKEN_INVALID);
       }
}

/**
    * 构建jwt
    * @param userId
    * @param username
    * @param role
    * @param audience
    * @return
    */
   public static String createJWT(String userId, String username, String role, Audience audience) {
try {
// 使用HS256加密算法
           SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

           long nowMillis = System.currentTimeMillis();
           Date now = new Date(nowMillis);

           //生成签名密钥
           byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(audience.getBase64Secret());
           Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

           //userId是重要信息,进行加密下
           String encryId = Base64Util.encode(userId);

           //添加构成JWT的参数
           JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT")
// 可以将基本不重要的对象信息放到claims
                   .claim("role", role)
.claim("userId", userId)
.setSubject(username) // 代表这个JWT的主体,即它的所有人
                   .setIssuer(audience.getClientId()) // 代表这个JWT的签发主体;
                   .setIssuedAt(new Date()) // 是一个时间戳,代表这个JWT的签发时间;
                   .setAudience(audience.getName()) // 代表这个JWT的接收对象;
                   .signWith(signatureAlgorithm, signingKey);
           //添加Token过期时间
           int TTLMillis = audience.getExpiresSecond();
           if (TTLMillis >= 0) {
long expMillis = nowMillis + TTLMillis;
               Date exp = new Date(expMillis);
               builder.setExpiration(exp) // 是一个时间戳,代表这个JWT的过期时间;
                       .setNotBefore(now); // 是一个时间戳,代表这个JWT生效的开始时间,意味着在这个时间之前验证JWT是会失败的
           }

//生成JWT
           return builder.compact();
       } catch (Exception e) {
log.error("签名失败", e);
           throw new CustomException(ResultCode.PERMISSION_SIGNATURE_ERROR);
       }
}

/**
    * token中获取用户名
    * @param token
    * @param base64Security
    * @return
    */
   public static String getUsername(String token, String base64Security){
return parseJWT(token, base64Security).getSubject();
   }

/**
    * token中获取用户ID
    * @param token
    * @param base64Security
    * @return
    */
   public static String getUserId(String token, String base64Security){
String userId = parseJWT(token, base64Security).get("userId", String.class);
       return Base64Util.decode(userId);
   }

/**
    * 是否已过期
    * @param token
    * @param base64Security
    * @return
    */
   public static boolean isExpiration(String token, String base64Security) {
return parseJWT(token, base64Security).getExpiration().before(new Date());
   }
}


拦截器:

@Autowired
private Audience audience;

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 忽略带JwtIgnore注解的请求, 不做后续token认证校验
   if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
       JwtIgnore jwtIgnore = handlerMethod.getMethodAnnotation(JwtIgnore.class);
       if (jwtIgnore != null) {
return true;
       }
}

if (HttpMethod.OPTIONS.equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
       return true;
   }

// 获取请求头信息authorization信息
   final String authHeader = request.getHeader(JwtTokenUtil.AUTH_HEADER_KEY);
   log.info("## authHeader= {}", authHeader);

   if (StringUtils.isBlank(authHeader) || !authHeader.startsWith(JwtTokenUtil.TOKEN_PREFIX)) {
log.info("### 用户未登录,请先登录 ###");
       throw new CustomException(ResultCode.USER_NOT_LOGGED_IN);
   }

// 获取token
   final String token = authHeader.substring(7);

   if(audience == null){
BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
       audience = (Audience) factory.getBean("audience");
   }

// 验证token是否有效--无效已做异常抛出,由全局异常处理后返回对应信息
   JwtTokenUtil.parseJWT(token, audience.getBase64Secret());

   return true;
}


发现了,以下问题:

1.没有对输入ID进行加密

2.没有用logger记录日志

3.JWT配置应该在配置文件中设置

4.没有设置过期时间,不过我的token是放在cookie当中,cookie设置了过期时间

5.密钥设置过于简单


这些打算在之后的项目进行修改






返回列表 返回列表
评论

    分享到