关于jwt的类dsl语义封装

说明:

  • 背景: 对于项目中原来自我封装的jwt工具类不尽如意, 相对稍显笨重, 另工具类需要告诉使用者如何使用,每人都要讲一遍比较麻烦, 因此, 重新封装了jwt工具类, 使其自带解释. 借鉴dsl语义, 借鉴alibaba cola状态机设计.
  • jwt中有一些必要参数,不分先后都可以,如此,在dsl调用链里就可以人为指定一种顺序(没有顺序本身也就意味着任何一种顺序都可以)

目录树

在这里插入图片描述

使用示例

public static void main(String[] args) throws InterruptedException, IOException {
        String key = UUID.randomUUID().toString();
        long l = LocalDateTime.now().plusSeconds(10).toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
        Date expireAt = new Date(l);
        Operator operator2 = JwtUtil.builder().secret(key).audience("admin").issure("admin").expireAt(expireAt).generator().build();
        System.out.println(operator2);
        TimeUnit.SECONDS.sleep(2);
        Operator operator3 = JwtUtil.builder().secret(key).audience("admin").issure("admin").token(operator2.getToken()).verify().build();
        System.out.println(operator3);
    }

可以看到上述的代码好似和我们熟知建造者模式类似, 但是在编译器里写的是否, 会发现, 你做了第一步之后,下一步是什么,是完全自动提示的, 不需要再有额外的文档阐述, 我觉得这种是非常好的,程序自带解释.
下面是idea的自动提示截图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
可以看到整个JwtUtil工具类已有了自我解释能力,我非常欣赏这样的工具包,就如cola的状态及,okhttp一样, 用起来是非常好用的.

整个源码如下,目前未上传github,后续会整理整套好用的工具包放入.


import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.util.*;

public class JwtUtil implements Builder, Secret, Audience, Issure, Token, ExpireAt, Generator, Verify, Operator {
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    private static final String BEARER = "Bearer ";

    private String secret;
    private String[] audience;
    private String issure;
    private String token;
    private Date expireAt;
    private String jwtId;
    private String keyId;
    private Date issuedAt;
    private final Map<String, Object> payload = new HashMap<>();
    private JWTVerifier jwtVerifier;
    private DecodedJWT decodedJWT;

    private JwtUtil() {

    }

    public static Builder builder() {
        return new JwtUtil();
    }

    @Override
    public Secret secret(String secret) {
        this.secret = secret;
        return this;
    }

    @Override
    public Audience audience(String... audience) {
        this.audience = audience;
        return this;
    }

    @Override
    public Issure issure(String issure) {
        this.issure = issure;
        return this;
    }

    @Override
    public Token token(String token) {
        this.token = token;
        return this;
    }

    @Override
    public ExpireAt expireAt(Date expireAt) {
        this.expireAt = expireAt;
        return this;
    }

    @Override
    public Generator generator(Map<String, Object> payload) {
        JWTCreator.Builder builder = JWT.create();
        this.issuedAt = new Date();
        this.jwtId = UUID.randomUUID().toString().toUpperCase();
        this.keyId = UUID.randomUUID().toString().toUpperCase();
        if (payload != null) {
            this.payload.putAll(payload);
        }
        builder
                .withExpiresAt(this.expireAt)
                .withIssuedAt(this.issuedAt)
                .withIssuer(this.issure)
                .withAudience(this.audience)
                .withJWTId(this.jwtId)
                .withKeyId(this.keyId)
                .withPayload(this.payload)
        ;
        this.token = BEARER+builder.sign(Algorithm.HMAC256(this.secret));
        this.payload.put("iss", this.issure);
        this.payload.put("aud", this.audience);
        this.payload.put("exp", this.expireAt.getTime() / 1000);
        this.payload.put("jti", this.jwtId);
        this.payload.put("iat", this.issuedAt.getTime()/1000);
        return this;
    }

    @Override
    public Generator generator() {
        return this.generator(null);
    }

    @Override
    public Verify verify() throws IOException {
        if (this.jwtVerifier == null) {
            this.jwtVerifier = JWT.require(Algorithm.HMAC256(secret)).build();

        }
        if (this.decodedJWT == null) {
            this.decodedJWT = jwtVerifier.verify(token.replace(BEARER,""));
            this.audience = this.decodedJWT.getAudience().toArray(new String[0]);
            this.issure = this.decodedJWT.getIssuer();
            this.issuedAt = this.decodedJWT.getIssuedAt();
            this.expireAt = this.decodedJWT.getExpiresAt();
            this.jwtId = this.decodedJWT.getId();
            this.keyId = this.decodedJWT.getKeyId();
            this.payload.putAll(OBJECT_MAPPER.readValue(Base64.getUrlDecoder().decode(this.decodedJWT.getPayload()), new TypeReference<Map<String, Object>>() {
            }));
        }
        return this;
    }

    @Override
    public Operator build() {
        return this;
    }

    @Override
    public String getSecret() {
        return this.secret;
    }

    @Override
    public String[] getAudience() {
        return this.audience;
    }

    @Override
    public String getIssure() {
        return this.issure;
    }

    @Override
    public String getToken() {
        return this.token;
    }

    @Override
    public Date getExpireAt() {
        return this.expireAt;
    }

    @Override
    public String getJwtId() {
        return this.jwtId;
    }

    @Override
    public String getKeyId() {
        return this.keyId;
    }

    @Override
    public Date getIssuedAt() {
        return this.issuedAt;
    }

    @Override
    public Map<String, ?> getPayload() {
        return this.payload;
    }

    @Override
    public boolean getClaimAsBool(String name) {
        String claimAsString = this.getClaimAsString(name);
        if (claimAsString == null) return false;
        return Boolean.parseBoolean(claimAsString);
    }

    @Override
    public int getClaimAsInt(String name) {
        String claimAsString = this.getClaimAsString(name);
        if (claimAsString == null) return 0;
        return Integer.parseInt(claimAsString);
    }

    @Override
    public long getClaimAsLong(String name) {
        String claimAsString = this.getClaimAsString(name);
        if (claimAsString == null) return 0;
        return Long.parseLong(claimAsString);
    }

    @Override
    public Object getClaim(String name) {
        return this.payload.get(name);
    }

    @Override
    public String getClaimAsString(String name) {
        if (name == null) return null;
        return String.valueOf(this.getClaim(name));
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("jwt:{");
        if (this.audience == null) {
            sb.append("audience=null");
        } else {
            sb.append("audience=").append(String.join(",",this.audience));
        }
        sb.append(",issure=").append(this.issure);
        sb.append(",token=").append(this.token);
        sb.append(",expireAt=").append(this.expireAt);
        sb.append(",jwtId=").append(this.jwtId);
        sb.append(",keyId=").append(this.keyId);
        sb.append(",issuedAt=").append(this.issuedAt);
        sb.append(",payload={");
        this.payload.forEach((k, v) -> {
            if (v.getClass().isArray()){
                if (Objects.equals(v.getClass().getComponentType().getTypeName(), String.class.getTypeName())){
                    String[] vv = (String[]) v;
                    sb.append(k).append("=").append(String.join(",", vv)).append(",");
                }else {
                    sb.append(k).append("=").append(v).append(",");
                }
            }else {
                sb.append(k).append("=").append(v).append(",");
            }
        });
        if (sb.charAt(sb.length() - 1) == ',') {
            sb.deleteCharAt(sb.length() - 1);
        }
        sb.append("}");
        sb.append("}");
        return sb.toString();
    }

}


import lombok.NonNull;

public interface Audience {
    Issure issure(@NonNull String issure);
}

import lombok.NonNull;

public interface Builder {
    Secret secret(@NonNull String secret);
}

import java.util.Map;

public interface ExpireAt {
    Generator generator(Map<String,Object> payload);

    Generator generator();
}

public interface Generator {
    Operator build();
}

import lombok.NonNull;

import java.util.Date;

public interface Issure {
    Token token(@NonNull String token);

    ExpireAt expireAt(@NonNull Date expireAt);
}


public interface Operator {

    String getSecret();

    String[] getAudience();

    String getIssure();

    String getToken();

    Date getExpireAt();

    String getJwtId();

    String getKeyId();

    Date getIssuedAt();

    Map<String,?> getPayload();

    boolean getClaimAsBool(String name);

    int getClaimAsInt(String name);

    long getClaimAsLong(String name);

    Object getClaim(String name);

    String getClaimAsString(String name);
}

import lombok.NonNull;

public interface Secret {
    Audience audience(@NonNull String... audience);
}


import java.io.IOException;

public interface Token {
    Verify verify() throws IOException;
}

public interface Verify {
    Operator build();
}

源码地址: https://github.com/zhangpan-soft/dv-commons

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Egg.js中封装JWT可以按照以下步骤进行: 1. 首先,安装jsonwebtoken库,使用npm install jsonwebtoken命令进行安装。 2. 在需要使用JWT的文件中引入jsonwebtoken库,使用var jwt = require('jsonwebtoken')语句。 3. 创建一个函数,用于生成token。在该函数中,使用jwt.sign方法来生成token。例如: ``` function generateToken(user) { // 生成token的逻辑 var token = jwt.sign(user, 'this is sign', { expiresIn: '1h' }); return token; } ``` 这个函数接受一个用户对象作为参数,并使用jwt.sign方法生成token。第一个参数是用户对象,第二个参数是签名字符串,第三个参数是可选的配置对象,例如设置token的过期时间。 4. 创建一个函数,用于验证token的合法性。在该函数中,使用jwt.verify方法来验证token。例如: ``` function verifyToken(token) { try { var decoded = jwt.verify(token, 'this is sign'); return decoded; } catch (error) { return null; } } ``` 这个函数接受一个token作为参数,并使用jwt.verify方法验证token的合法性。如果验证成功,返回解码后的token内容,否则返回null。 5. 将生成token和验证token的函数导出,以供其他文件使用。 这样,你就可以在Egg.js中封装JWT并使用了。请注意,上述代码仅为示例,你可以根据实际需求进行修改和扩展。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Eggjs笔记:关于JWT的接口权限验证](https://blog.csdn.net/Tyro_java/article/details/106583547)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值