需求背景

Joget默认的网络服务插件是平台级且完全开放的, 如果你在基础设置里面设置了域名白名单为 *, 且服务器部署在外网 ,这会导致你的网络接口可以被所有人请求到.

如果有黑客恶意攻击,可能会有不可预知的风险.因此,我们在这里引入了JWT http://jwt.io 作为网络服务的安全机制.

JWT简介

参见 https://jwt.io/introduction/

如何使用

1.引入Maven依赖

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.8.2</version>
</dependency>

2.Jwt工具类

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import org.joget.commons.util.LogUtil;

import java.util.Date;

public class JWTUtil {

    /**
     * 创建token
     * @param expire_time 单位秒,过期时间
     * @return
     */
    public static String createToken(String id,Long expire_time){
        Date expiresDate = new Date(System.currentTimeMillis() + expire_time*1000 );
        String token = "";
        try {
            Algorithm algorithm = Algorithm.HMAC256("secret");
            token = JWT.create()
                    .withKeyId(id)
                    .withExpiresAt(expiresDate)
                    .withIssuer("zihao")
                    .sign(algorithm);
        } catch (JWTCreationException exception){
            //Invalid Signing configuration / Couldn't convert Claims.
        }
        return token;
    }


    /**
     * 解析token
     * @return
     */
    public static DecodedJWT verifyToken(String token){
        try {
            Algorithm algorithm = Algorithm.HMAC256("secret");
            JWTVerifier verifier = JWT.require(algorithm)
                    .build(); //Reusable verifier instance
            DecodedJWT jwt = verifier.verify(token);
            return jwt;
        } catch (JWTVerificationException e){
            //Invalid signature/claims
            //LogUtil.info("JWTUtil",e.getMessage());
        }
        return  null;

    }


    public static void main(String[] args) {
        String id = "uuid";
        String token = JWTUtil.createToken(id,1L);
//        try {
//            Thread.sleep(2L*1000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

        DecodedJWT jwt = JWTUtil.verifyToken(token);
        String keyId = jwt.getKeyId();
        String jwtIssuer = jwt.getIssuer();
        System.out.println("keyId : "+ keyId);
        System.out.println("issuer : " + jwtIssuer);
    }

}


3. 完善你自己的网络服务接口

  1. 接口需要通过参数控制获取token,同时生成UID
  2. 接口附带token请求需要验证token的有效期和UID(UID和Token放在Header中)
if (get_jwt_token.equalsIgnoreCase("get_jwt_token")){
    String uid = UUID.randomUUID().toString();
    String token = JWTUtil.createToken(uid,120L);
    result.put("errcode", "0");
    result.put("errmsg", "请求成功");
    result.put("uid", uid);
    result.put("jwt_token", token);
    result.write(response.getWriter());
    return;
}else if (StringUtils.isEmpty(request.getHeader("jwt-token"))){
    result.put("errcode", "40001");
    result.put("errmsg", "缺少TOKEN");
    result.write(response.getWriter());
    return;
}
if (!StringUtils.isEmpty(jwt_token)){
    DecodedJWT jwt = JWTUtil.verifyToken(jwt_token);
    //如果jwt为空,则秘钥过期
    if (StringUtils.isEmpty(jwt)){
        result.put("errcode", "40001");
        result.put("errmsg", "TOKEN已过期");
        result.write(response.getWriter());
        return;
    }else {
        String id = jwt.getKeyId();
        String uid = request.getHeader("uid");
        //LogUtil.info( getClass().getName(), "id :  " + id);
        //LogUtil.info( getClass().getName(), "uid : " + uid);
        if (StringUtils.isEmpty(uid) ||
                !uid.equals(id)){
            result.put("errcode", "40001");
            result.put("errmsg", "UID不正确");
            result.write(response.getWriter());
            return;
        }
        LogUtil.info( getClass().getName(), "token verify success ! ");
    }
}


  • No labels