《Java实战开发》基于JWT实现简单信息分享

《Java实战开发》基于JWT实现简单信息分享,第1张

《Java实战开发》基于JWT实现简单信息分享

公司有个合作伙伴替用户下单的需求,下单完毕需要将单据信息分享给客户看,让客户付款。由于只是一些简单的单据信息,并且没有权限校验,综合考虑安全与性能,决定使用JWT的方式实现。

JWT简介

JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案。具体概念自行搜索
官网介绍如下:
https://jwt.io/introduction

主要代码实现
public enum SingletonRsaJsonWebKeyEnum {
    //创建一个枚举对象,该对象天生为单例
    INSTANCE;

    private RsaJsonWebKey generateJwk() {
        RsaJsonWebKey rsaJsonWebKey = null;

        try {
            rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
            rsaJsonWebKey.setKeyId("www_key_customer_pay");
        } catch (JoseException e) {
            e.printStackTrace();
        }
        return rsaJsonWebKey;
    }

    public String getRsaJsonWebKeyJsonString() {
        String keyString =        "{"kty":"RSA","kid":"www_key_customer_pay","n":"lZJmKh4hM5_B0Cw2zUajuXhi6g-ZiWoNKAYIkC4upx8B9PtE541lwu6qYYoS_gP5K1tOTgJodwK95j8kfmq2Nevr8hr9FuROic0xftOJTJrkwsun22X73d5IhvG01t0NB-S_WmYF-JRcmJ6zQD1nnFgMTHn3zhEJrxByrsad-yGb0cdzFX8R4Ae383c8dL2VWyJRTOMAqW_fuR3TpSdFd-fYmjadmLIdodsWPchR88ZeEURYLjPgYAVbtBmfe8npIWHNKyPgnuy0JWdR7FQQFXvU5c-f4wccErB_o5oGHt4Nm8-S5cC3T0yp9e1CKaSiUOTCvwFfq5cX4Rf8WDzNyQ","e":"AQAB","d":"VvOTxvpbDNrb3jxF45IkTgcpYa6N8G-hlFnlkoP2hRsmlReZ2A7AUNFUZX3SSq9epBDhdcI6nq0OXpLokUFSCgjL0qRT64HwEnYiRvuMvubxBDlGrOodwL6fZSuQmLRLBgK6J0BWSktdhTAFPtwzppUdGTxyje4jtg0WznoSj1H3Gx6XN98_Nut2r5hXqP1f1nsdsE1dCaTYIJnf4kTpRBoEMjLQ2qoFr77e-wSmIrc4HFOaVzJCN4NQZjx_Vi3CdV33QX3qWEypfihEC25yGH4k7MLaP7ZSzqwv2VcvB5O7DAImYrJwQSSofiNE5yXqL6g8_0zYe91ardZngy6KzQ","p":"1UWnxrs4FdLzfi2060zfXKiEDqAh2-XLaEtlT3fUOe3Acxb0PTzRmQICwttd1pqAvqwljdapbkOHIBiGSOeQWJQEsCVxymaUVOtWxWImZmREJh8L2KoPfUIHENOmx76FmczOtTpQi4cvUnzVy45iIshC28zePTYX7l7UdxHufmM","q":"s4msVx1gdrYiCVv58db3jfXaKYWDYI8-8Fp_KdyKCFPmayYYeWl9wUEouywLqguwKKyRo7h2lKMEcgmQp0DniZVZpFpzxBu9rkmpbsS2xHL2FDt5cueNS_xgvVS3okmrW6rz6_ufBnjXKSGRMn8ZqZs6jDDdAZ-fD9iuOmCBFOM","dp":"JnmFdf2qdY1z7exy-gwJM58XC8hps1D2bB9F7JsyhyzUDi8y6qVBLrhFJUAL4r5GwZ8uuzLhqAm4o9qoxxg3WzOA0QJAUAJHejZmlf9J7CjkfngVXAX5-1_hBHEaYmiFk6R2Gg2mIDXIHLp2m11ZaOr13M9NvH84vAERlVV_z_8","dq":"C9ncnGt-AJgJKyD9IK-V67L80ZzUjT0nZGo01qiOG_qdzRjYqLsD6AvLCn_fzTu0RxsNCgeVHD6efoCPIdsw7W4EWsr1tU43eRe3rW4iulj0UWWToLgUJZ3lLNo4vOer_gMM0tjrKFw1p6tlkDW_leh_Nt3K2N6We09MQOI54w0","qi":"g66xqKV_Ci2gVgylelYk7FbypqhRsUDBrbqBZUaEK0nIW3HZGsqKB1g55vO60R4_lhftFTwrkabBtGipt6fRk3GPywj1usp3AVtR0uvBNPHGAiTYJ0hEd98uiwMQ2MteZuj3Iy-RIs9BHlN2QJVTgfZ_ulgO_viMQlfQNxrBfcA"}n"
;
//        if (keyString == null) {
//            keyString = SingletonRsaJsonWebKeyEnum.INSTANCE.generateJwk().toJson(RsaJsonWebKey.OutputControlLevel.INCLUDE_PRIVATE);
//        }
        return keyString;
    }

//    public static void main(String[] args) {
//
//        String keyString = SingletonRsaJsonWebKeyEnum.INSTANCE.generateJwk().toJson(RsaJsonWebKey.OutputControlLevel.INCLUDE_PRIVATE);
//        RsaJsonWebKey  rsaJsonWebKey = new RsaJsonWebKey(JsonUtil.parseJson(SingletonRsaJsonWebKeyEnum.INSTANCE.getRsaJsonWebKeyJsonString()));
//
//    }
}
@Slf4j
public class JwtUtils {
    public static RsaJsonWebKey rsaJsonWebKey;

    static {
        try {
            rsaJsonWebKey = new RsaJsonWebKey(JsonUtil.parseJson(SingletonRsaJsonWebKeyEnum.INSTANCE.getRsaJsonWebKeyJsonString()));
        } catch (JoseException e) {
            e.printStackTrace();
        }
    }

    private JwtUtils() {
    }

    public static String createToken(Object jsonString) throws JoseException {
        //
        // JSON Web Token is a compact URL-safe means of representing claims/attributes to be transferred between two parties.
        // This example demonstrates producing and consuming a signed JWT
        //
//        RsaJsonWebKey rsaJsonWebKey = SingletonRsaJsonWebKeyEnum.generateJwk();

        // Give the JWK a Key ID (kid), which is just the polite thing to do


        // Create the Claims, which will be the content of the JWT
        JwtClaims claims = new JwtClaims();
        claims.setIssuer("WWW");  // who creates the token and signs it
        claims.setAudience("WWW_CUSTOMER"); // to whom the token is intended to be sent
        claims.setExpirationTimeMinutesInTheFuture(48 * 60); // time when the token will expire ( minutes from now)
        claims.setGeneratedJwtId(); // a unique identifier for the token
        claims.setIssuedAtToNow();  // when the token was issued/created (now)
        claims.setNotBeforeMinutesInThePast(2); // time before which the token is not yet valid (2 minutes ago)
        claims.setSubject("测试Token"); // the subject/principal is whom the token is about
        claims.setClaim("data", jsonString); // additional claims/attributes about the subject can be added
//        List groups = Arrays.asList("group-one", "other-group", "group-three");
//        claims.setStringListClaim("groups", groups); // multi-valued claims work too and will end up as a JSON array

        // A JWT is a JWS and/or a JWE with JSON claims as the payload.
        // In this example it is a JWS so we create a JsonWebSignature object.
        JsonWebSignature jws = new JsonWebSignature();

        // The payload of the JWS is JSON content of the JWT Claims
        jws.setPayload(claims.toJson());

        // The JWT is signed using the private key
        jws.setKey(rsaJsonWebKey.getPrivateKey());

        // Set the Key ID (kid) header because it's just the polite thing to do.
        // We only have one key in this example but a using a Key ID helps
        // facilitate a smooth key rollover process
        jws.setKeyIdHeaderValue(rsaJsonWebKey.getKeyId());

        // Set the signature algorithm on the JWT/JWS that will integrity protect the claims
        jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);

        // Sign the JWS and produce the compact serialization or the complete JWT/JWS
        // representation, which is a string consisting of three dot ('.') separated
        // base64url-encoded parts in the form Header.Payload.Signature
        // If you wanted to encrypt it, you can simply set this jwt as the payload
        // of a JsonWebEncryption object and set the cty (Content Type) header to "jwt".
        String jwt = jws.getCompactSerialization();


        // Now you can do something with the JWT. Like send it to some other party
        // over the clouds and through the interwebs.
        return jwt;

    }


    public static JwtClaims validateToken(String jwt)  {

//        RsaJsonWebKey rsaJsonWebKey = SingletonRsaJsonWebKeyEnum.generateJwk();
        // Use JwtConsumerBuilder to construct an appropriate JwtConsumer, which will
        // be used to validate and process the JWT.
        // The specific validation requirements for a JWT are context dependent, however,
        // it typically advisable to require a (reasonable) expiration time, a trusted issuer, and
        // and audience that identifies your system as the intended recipient.
        // If the JWT is encrypted too, you need only provide a decryption key or
        // decryption key resolver to the builder.
        JwtConsumer jwtConsumer = new JwtConsumerBuilder()
                .setRequireExpirationTime() // the JWT must have an expiration time
                .setAllowedClockSkewInSeconds(30) // allow some leeway in validating time based claims to account for clock skew
                .setRequireSubject() // the JWT must have a subject claim
                .setExpectedIssuer("WWW") // whom the JWT needs to have been issued by
                .setExpectedAudience("WWW_CUSTOMER") // to whom the JWT is intended for
                .setVerificationKey(rsaJsonWebKey.getKey()) // verify the signature with the public key
                .setJwsAlgorithmConstraints( // only allow the expected signature algorithm(s) in the given context
                        AlgorithmConstraints.ConstraintType.PERMIT, AlgorithmIdentifiers.RSA_USING_SHA256) // which is only RS256 here
                .build(); // create the JwtConsumer instance
        JwtClaims jwtClaims = null;
        try {
            //  Validate the JWT and process it to the Claims
            jwtClaims = jwtConsumer.processToClaims(jwt);
            log.info("JWT validation succeeded! " + jwtClaims);
        } catch (InvalidJwtException e) {
            // InvalidJwtException will be thrown, if the JWT failed processing or validation in anyway.
            // Hopefully with meaningful explanations(s) about what went wrong.
            log.error("Invalid JWT! " + e);

            // Programmatic access to (some) specific reasons for JWT invalidity is also possible
            // should you want different error handling behavior for certain conditions.

            // Whether or not the JWT has expired being one common reason for invalidity
            try {
                if (e.hasExpired()) {
                    log.error("JWT expired at " + e.getJwtContext().getJwtClaims().getExpirationTime());
                }

                // Or maybe the audience was invalid
                if (e.hasErrorCode(ErrorCodes.AUDIENCE_INVALID)) {
                    log.error("JWT had wrong audience: " + e.getJwtContext().getJwtClaims().getAudience());
                }
            }catch (MalformedClaimException  e1){
                log.error("验证客户支付token异常",e1);
            }

            throw new MallBusinessException(StatusEnum.CUSTOMER_PAY_TOKEN_AUTHENTICATION_ERROR);
        }

        return jwtClaims;
    }

 

    public static void main(String[] args) throws Exception {
        String json = "{"name":"小二","age":"18"}";
        String jwt = createToken(json);
//        String jwt = "eyJraWQiOiJ5empfa2V5X2N1c3RvbWVyX3BheSIsImFsZyI6IlJTMjU2In0.eyJpc3MiOiJZWkoiLCJhdWQiOiJZWkpfQ1VTVE9NRVIiLCJleHAiOjE2MzQxMTI2MDQsImp0aSI6Ikl5VXJYS2FkQkNSUThTODMwTVBpSFEiLCJpYXQiOjE2MzQxMTI1NDQsIm5iZiI6MTYzNDExMjQyNCwic3ViIjoi5LqR5LmL5a625Zyo57q_5ZWG5Z-O5a6i5oi35L6n5pSv5LuYVG9rZW4iLCJkYXRhIjoie1wibmFtZVwiOlwi5bCP5LqMXCIsXCJhZ2VcIjpcIjE4XCJ9In0.hfN9FxUOpr52QlYcpONswFhCYiwNWezeRAOU9iMZTNuIdJownd4Aku4trvsvSqw6FmlgwikdjDkBK8jz3mkyREeEzqlbQmlcB2Z8cz2ASy7v1mNoKvmha8l0uJ04H7c6Tottq_Ktr74ENVaaWRV-EkINHqFfg86CSiuueriEal0JKErYQGUPhWT1IO36s_sPHxAN3TzOgDBkkICxmf9ty1EgxQ3GXY_BRWdIFM4QoztLq2US0bxfNZZbBG4eE8dG3AwBDbQrjN4ESxDeXmuaqODVySRb2Nr1B-F0cT5DPJgrSH1cYqsy-BjOKdLDlBgA16ACYq8MebCCkFz3VNwGkA";
        JwtClaims result = validateToken(jwt);
        System.out.println("开始:" + jwt);
        System.out.println("结果:" + result.getClaimValue("data"));
        System.out.println("结果:" + result);
        System.out.println("结果:" + result.getExpirationTime());
    }




}
### 测试结果

开始:eyJraWQiOiJ5empfa2V5X2N1c3RvbWVyX3BheSIsImFsZyI6IlJTMjU2In0.eyJpc3MiOiJZWkoiLCJhdWQiOiJZWkpfQ1VTVE9NRVIiLCJleHAiOjE2MzQ3MzE0NTcsImp0aSI6ImR6UXJZeVg2c2EydjFWRmJ1S1ZQX0EiLCJpYXQiOjE2MzQ1NTg2NTgsIm5iZiI6MTYzNDU1ODUzOCwic3ViIjoi5LqR5LmL5a625Zyo57q_5ZWG5Z-O5a6i5oi35L6n5pSv5LuYVG9rZW4iLCJkYXRhIjoie1wibmFtZVwiOlwi5bCP5LqMXCIsXCJhZ2VcIjpcIjE4XCJ9In0.YIq2OgIdI2l676aFN92HH4_gKjwPSE4TZRN01ADk3XXKIseXFCmYc7Sl2VhoF762oFylnJk_PUZgVST1scSQzKhm7L2-mSEqO3-xyV7tUmV06TmLHq5qoW6dxVLxhpo2hsYT9uLryDMyln-Is1cZXCSu8zhop75AYKjpJ-7xImxIFR9SgVo7pOpcSIsiZd3lzfUbvpNRb26CyAegpphKofVRMM6ZjhRQRY7YqzxLaNQiSMNiJMsuDO7XSbXIfUSHJPFwoq_Nq66ebt2O5830pDu38DdKcTfY3w7vbHOewYTHgVCngVFF4UUD-f76kfw2n5GwGIgmYK4JAfDgj6qTnw
结果:{“name”:“小二”,“age”:“18”}
结果:JWT Claims Set:{iss=YZJ, aud=YZJ_CUSTOMER, exp=1634731457, jti=dzQrYyX6sa2v1VFbuKVP_A, iat=1634558658, nbf=1634558538, sub=云之家在线商城客户侧支付Token, data={“name”:“小二”,“age”:“18”}}
结果:NumericDate{1634731457 -> 2021-10-20 下午08时04分17秒}

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/4658451.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-11-06
下一篇2022-11-06

发表评论

登录后才能评论

评论列表(0条)

    保存