用户登录的详细流程(二)JWT生成token登录

2023-11-15

JWT生成token登录

1.jwt的构成
(1)header
(2)payload
(3)signature
2.token的登陆原理
3.在实际中如何应用token
(1)设置token的生成代码
(2)如何从token中获取有用的信息
(3)验证token
(4)实践得到的结果
4.附录
(1)创建token所用的源码
(2)获取token信息的源码

1.JWT的构成

header(头部) payload(载荷) signature(签名)

(1)header 承接两部分信息

声明类型: jwt
声明加密算法: 一般使用的是HMAC SHA256

完整的头部就像下面这样的JSON:

{
"typ": "JWT",

"alg": "HS256"

}

(2)payload 存放有效信息的地方

可以大致分为三部分
标注中的注册声明: 可以再token中存放自定义的字段,但是要注意不能存放一些关键信息
公共声明:公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密.
私有声明:私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。

标注中的注册声明:
iss:jwt的签发者
sub:jwt所面向的用户
aud:接收jwt的一方
exp:jwt的过期时间,就是token的有限期限
nbf:定义在什么时间之前jwt都不可以用
iat:jwt的签发时间
jti:jwt唯一身份标识,主要用来生成一次性的token

(3)signature(签证)

是根据加密算法得到的数据,其中加密的密钥是存在在后端服务器中,然后这三个部分连接起来就是一个token

2.token登录的原理

首先用户输入账号和密码进行登录,后端根据数据库进行验证用户,验证通过生成token。然后前端将后端返回的token保存起来,每次用户访问请求都带着token,在后端经过拦截器的拦截,然后再进行判断,如果token验证通过放行,否则不能让用户访问界面。

3.在实际中如何应用token

(1)设置token的生成代码

    /**
     * token携带id和name
     */
    private static final String CLAIM_KEY_ID = "sub";//系统自带的
    private static final String CLAIM_KEY_NAME = "name";//自定义的

    /**
     * token生成时间
     */
    private static final String CLAIM_KEY_CREATED = "created";

    @Value("${jwt.secret}")
    private String secret;

    @Value("${jwt.expire}")
    private int expire;

    public String createToken(Long id,String name) {

        Date date = DateUtil.offset(new Date(), DateField.DAY_OF_YEAR, expire);//设置过期时间,其中这个expire是自己设置的时间,可以定义一个常量,也可以在通过注入的方式,将其配置在xml中。
        Algorithm algorithm = Algorithm.HMAC256(secret);//使用jwt类的Algorithm 对象,去对密钥(第三部分的签证)进行加密
        JWTCreator.Builder builder = JWT.create();//使用jwt的对应的类的方法将jwt的三部分组成结合起来,形成一个token。
        String token = builder
                .withClaim(CLAIM_KEY_ID, id)
                .withClaim(CLAIM_KEY_NAME, name)
                .withClaim(CLAIM_KEY_CREATED, new Date())
                .withExpiresAt(date)
                .sign(algorithm);
                //以上都是Builder的方法,我已放在后面。
        return token;

    }
	/**
	 * 获取指定日期偏移指定时间后的时间,生成的偏移日期不影响原日期
	 *
	 * @param date      基准日期
	 * @param dateField 偏移的粒度大小(小时、天、月等){@link DateField}
	 * @param offset    偏移量,正数为向后偏移,负数为向前偏移
	 * @return 偏移后的日期
	 */
	public static DateTime offset(Date date, DateField dateField, int offset) {
		return dateNew(date).offset(dateField, offset);
	}

//这是他的简介
/**
 * The Algorithm class represents an algorithm to be used in the Signing or Verification process of a Token.
 */
 /** * Algorithm 类表示在令牌的签名或验证过程中使用的算法。 */

    /**
     * Creates a new Algorithm instance using HmacSHA256. Tokens specify this as "HS256".
     *
     * @param secret the secret to use in the verify or signing instance.
     * @return a valid HMAC256 Algorithm.
     * @throws IllegalArgumentException     if the provided Secret is null.
     */
     /** * 使用 HmacSHA256 创建一个新的算法实例。令牌将其指定为“HS256”。 * * @param secret 在验证或签名实例中使用的秘密。 * @return 有效的 HMAC256 算法。 * @throws IllegalArgumentException 如果提供的 Secret 为空。 */
     
    public static Algorithm HMAC256(String secret) throws IllegalArgumentException {
        return new HMACAlgorithm("HS256", "HmacSHA256", secret);
    }

/**
 * The JWTCreator class holds the sign method to generate a complete JWT (with Signature) from a given Header and Payload content.
 */
 /** * JWTCreator 类包含 sign 方法,用于从给定的 Header 和 Payload 内容生成完整的 JWT(带签名)。 */
@SuppressWarnings("WeakerAccess")
public final class JWTCreator {

    private final Algorithm algorithm;
    private final String headerJson;
    private final String payloadJson;
    //截取部分源码

(2)如何从token中获取有用的信息

    /**
     * 从token中获取id
     * 
     *
     * @param token token
     * @return 用户id
     */
    public Long getIdFromToken(String token) {
        DecodedJWT jwt = JWT.decode(token);// DecodedJWT是用来解码token
        Long id = jwt.getClaim(CLAIM_KEY_ID).asLong();
        return accountId;
    }

           /**
     * 从token中获取name
     *
     * @param token token
     * @return 用户name
     */
         public String getNameFromToken(String token) {
        DecodedJWT jwt = JWT.decode(token);
        String name=jwt.getClaim(CLAIM_KEY_NAME).asString();
        return accountId;
    }

(3)验证token

    /**
     * 验证token
     * 验证成功什么也不返回,验证失败抛出JWTVerificationException异常
     *
     * @param token token
     */
     //固定写法就对了
    public void verifierToken(String token) {
        Algorithm algorithm = Algorithm.HMAC256(secret);
        JWTVerifier verifier = JWT.require(algorithm).build();
        verifier.verify(token);
    }
  

(4)实践得到的结果
代码
代码
这上面只是测试,可以看到详细的结果。和上面的实际代码有些冲突。

4.附录

(1)创建token所用的源码

    /**
     * The Builder class holds the Claims that defines the JWT to be created.
     */
     /** * Builder 类包含定义要创建的 JWT 的 Claims。 */
    public static class Builder {
        private final Map<String, Object> payloadClaims;
        private Map<String, Object> headerClaims;

        Builder() {
            this.payloadClaims = new HashMap<>();
            this.headerClaims = new HashMap<>();
        }

        /**
         * Add specific Claims to set as the Header.
         * If provided map is null then nothing is changed
         * If provided map contains a claim with null value then that claim will be removed from the header
         *
         * @param headerClaims the values to use as Claims in the token's Header.
         * @return this same Builder instance.
         */
        public Builder withHeader(Map<String, Object> headerClaims) {
            if (headerClaims == null) {
                return this;
            }

            for (Map.Entry<String, Object> entry : headerClaims.entrySet()) {
                if (entry.getValue() == null) {
                    this.headerClaims.remove(entry.getKey());
                } else {
                    this.headerClaims.put(entry.getKey(), entry.getValue());
                }
            }

            return this;
        }

        /**
         * Add a specific Key Id ("kid") claim to the Header.
         * If the {@link Algorithm} used to sign this token was instantiated with a KeyProvider, the 'kid' value will be taken from that provider and this one will be ignored.
         *
         * @param keyId the Key Id value.
         * @return this same Builder instance.
         */
        public Builder withKeyId(String keyId) {
            this.headerClaims.put(PublicClaims.KEY_ID, keyId);
            return this;
        }

        /**
         * Add a specific Issuer ("iss") claim to the Payload.
         *
         * @param issuer the Issuer value.
         * @return this same Builder instance.
         */
        public Builder withIssuer(String issuer) {
            addClaim(PublicClaims.ISSUER, issuer);
            return this;
        }

        /**
         * Add a specific Subject ("sub") claim to the Payload.
         *
         * @param subject the Subject value.
         * @return this same Builder instance.
         */
        public Builder withSubject(String subject) {
            addClaim(PublicClaims.SUBJECT, subject);
            return this;
        }

        /**
         * Add a specific Audience ("aud") claim to the Payload.
         *
         * @param audience the Audience value.
         * @return this same Builder instance.
         */
        public Builder withAudience(String... audience) {
            addClaim(PublicClaims.AUDIENCE, audience);
            return this;
        }

        /**
         * Add a specific Expires At ("exp") claim to the Payload.
         *
         * @param expiresAt the Expires At value.
         * @return this same Builder instance.
         */
        public Builder withExpiresAt(Date expiresAt) {
            addClaim(PublicClaims.EXPIRES_AT, expiresAt);
            return this;
        }

        /**
         * Add a specific Not Before ("nbf") claim to the Payload.
         *
         * @param notBefore the Not Before value.
         * @return this same Builder instance.
         */
        public Builder withNotBefore(Date notBefore) {
            addClaim(PublicClaims.NOT_BEFORE, notBefore);
            return this;
        }

        /**
         * Add a specific Issued At ("iat") claim to the Payload.
         *
         * @param issuedAt the Issued At value.
         * @return this same Builder instance.
         */
        public Builder withIssuedAt(Date issuedAt) {
            addClaim(PublicClaims.ISSUED_AT, issuedAt);
            return this;
        }

        /**
         * Add a specific JWT Id ("jti") claim to the Payload.
         *
         * @param jwtId the Token Id value.
         * @return this same Builder instance.
         */
        public Builder withJWTId(String jwtId) {
            addClaim(PublicClaims.JWT_ID, jwtId);
            return this;
        }

        /**
         * Add a custom Claim value.
         *
         * @param name  the Claim's name.
         * @param value the Claim's value.
         * @return this same Builder instance.
         * @throws IllegalArgumentException if the name is null.
         */
        public Builder withClaim(String name, Boolean value) throws IllegalArgumentException {
            assertNonNull(name);
            addClaim(name, value);
            return this;
        }

        /**
         * Add a custom Claim value.
         *
         * @param name  the Claim's name.
         * @param value the Claim's value.
         * @return this same Builder instance.
         * @throws IllegalArgumentException if the name is null.
         */
        public Builder withClaim(String name, Integer value) throws IllegalArgumentException {
            assertNonNull(name);
            addClaim(name, value);
            return this;
        }

        /**
         * Add a custom Claim value.
         *
         * @param name  the Claim's name.
         * @param value the Claim's value.
         * @return this same Builder instance.
         * @throws IllegalArgumentException if the name is null.
         */
        public Builder withClaim(String name, Long value) throws IllegalArgumentException {
            assertNonNull(name);
            addClaim(name, value);
            return this;
        }

        /**
         * Add a custom Claim value.
         *
         * @param name  the Claim's name.
         * @param value the Claim's value.
         * @return this same Builder instance.
         * @throws IllegalArgumentException if the name is null.
         */
        public Builder withClaim(String name, Double value) throws IllegalArgumentException {
            assertNonNull(name);
            addClaim(name, value);
            return this;
        }

        /**
         * Add a custom Claim value.
         *
         * @param name  the Claim's name.
         * @param value the Claim's value.
         * @return this same Builder instance.
         * @throws IllegalArgumentException if the name is null.
         */
        public Builder withClaim(String name, String value) throws IllegalArgumentException {
            assertNonNull(name);
            addClaim(name, value);
            return this;
        }

        /**
         * Add a custom Claim value.
         *
         * @param name  the Claim's name.
         * @param value the Claim's value.
         * @return this same Builder instance.
         * @throws IllegalArgumentException if the name is null.
         */
        public Builder withClaim(String name, Date value) throws IllegalArgumentException {
            assertNonNull(name);
            addClaim(name, value);
            return this;
        }

        /**
         * Add a custom Array Claim with the given items.
         *
         * @param name  the Claim's name.
         * @param items the Claim's value.
         * @return this same Builder instance.
         * @throws IllegalArgumentException if the name is null.
         */
        public Builder withArrayClaim(String name, String[] items) throws IllegalArgumentException {
            assertNonNull(name);
            addClaim(name, items);
            return this;
        }

        /**
         * Add a custom Array Claim with the given items.
         *
         * @param name  the Claim's name.
         * @param items the Claim's value.
         * @return this same Builder instance.
         * @throws IllegalArgumentException if the name is null.
         */
        public Builder withArrayClaim(String name, Integer[] items) throws IllegalArgumentException {
            assertNonNull(name);
            addClaim(name, items);
            return this;
        }

        /**
         * Add a custom Array Claim with the given items.
         *
         * @param name  the Claim's name.
         * @param items the Claim's value.
         * @return this same Builder instance.
         * @throws IllegalArgumentException if the name is null
         */
        public Builder withArrayClaim(String name, Long[] items) throws IllegalArgumentException {
            assertNonNull(name);
            addClaim(name, items);
            return this;
        }

        /**
         * Add a custom Map Claim with the given items.
         * <p>
         * Accepted nested types are {@linkplain Map} and {@linkplain List} with basic types
         * {@linkplain Boolean}, {@linkplain Integer}, {@linkplain Long}, {@linkplain Double},
         * {@linkplain String} and {@linkplain Date}. {@linkplain Map}s cannot contain null keys or values.
         * {@linkplain List}s can contain null elements.
         *
         * @param name the Claim's name.
         * @param map  the Claim's key-values.
         * @return this same Builder instance.
         * @throws IllegalArgumentException if the name is null, or if the map contents does not validate.
         */
        public Builder withClaim(String name, Map<String, ?> map) throws IllegalArgumentException {
            assertNonNull(name);
            // validate map contents
            if (map != null && !validateClaim(map)) {
                throw new IllegalArgumentException("Expected map containing Map, List, Boolean, Integer, Long, Double, String and Date");
            }
            addClaim(name, map);
            return this;
        }

        /**
         * Add a custom List Claim with the given items.
         * <p>
         * Accepted nested types are {@linkplain Map} and {@linkplain List} with basic types
         * {@linkplain Boolean}, {@linkplain Integer}, {@linkplain Long}, {@linkplain Double},
         * {@linkplain String} and {@linkplain Date}. {@linkplain Map}s cannot contain null keys or values.
         * {@linkplain List}s can contain null elements.
         *
         * @param name the Claim's name.
         * @param list the Claim's list of values.
         * @return this same Builder instance.
         * @throws IllegalArgumentException if the name is null, or if the list contents does not validate.
         */

        public Builder withClaim(String name, List<?> list) throws IllegalArgumentException {
            assertNonNull(name);
            // validate list contents
            if (list != null && !validateClaim(list)) {
                throw new IllegalArgumentException("Expected list containing Map, List, Boolean, Integer, Long, Double, String and Date");
            }
            addClaim(name, list);
            return this;
        }

        private static boolean validateClaim(Map<?, ?> map) {
            // do not accept null values in maps
            for (Entry<?, ?> entry : map.entrySet()) {
                Object value = entry.getValue();
                if (value == null || !isSupportedType(value)) {
                    return false;
                }

                if (entry.getKey() == null || !(entry.getKey() instanceof String)) {
                    return false;
                }
            }
            return true;
        }

        private static boolean validateClaim(List<?> list) {
            // accept null values in list
            for (Object object : list) {
                if (object != null && !isSupportedType(object)) {
                    return false;
                }
            }
            return true;
        }

        private static boolean isSupportedType(Object value) {
            if (value instanceof List) {
                return validateClaim((List<?>) value);
            } else if (value instanceof Map) {
                return validateClaim((Map<?, ?>) value);
            } else {
                return isBasicType(value);
            }
        }

        private static boolean isBasicType(Object value) {
            Class<?> c = value.getClass();

            if (c.isArray()) {
                return c == Integer[].class || c == Long[].class || c == String[].class;
            }
            return c == String.class || c == Integer.class || c == Long.class || c == Double.class || c == Date.class || c == Boolean.class;
        }

        /**
         * Creates a new JWT and signs is with the given algorithm
         *
         * @param algorithm used to sign the JWT
         * @return a new JWT token
         * @throws IllegalArgumentException if the provided algorithm is null.
         * @throws JWTCreationException     if the claims could not be converted to a valid JSON or there was a problem with the signing key.
         */
        public String sign(Algorithm algorithm) throws IllegalArgumentException, JWTCreationException {
            if (algorithm == null) {
                throw new IllegalArgumentException("The Algorithm cannot be null.");
            }
            headerClaims.put(PublicClaims.ALGORITHM, algorithm.getName());
            if (!headerClaims.containsKey(PublicClaims.TYPE)) {
                headerClaims.put(PublicClaims.TYPE, "JWT");
            }
            String signingKeyId = algorithm.getSigningKeyId();
            if (signingKeyId != null) {
                withKeyId(signingKeyId);
            }
            return new JWTCreator(algorithm, headerClaims, payloadClaims).sign();
        }

        private void assertNonNull(String name) {
            if (name == null) {
                throw new IllegalArgumentException("The Custom Claim's name can't be null.");
            }
        }

        private void addClaim(String name, Object value) {
            if (value == null) {
                payloadClaims.remove(name);
                return;
            }
            payloadClaims.put(name, value);
        }
    }

(2)获取token信息的源码

package com.auth0.jwt.interfaces;

/**
 * Class that represents a Json Web Token that was decoded from it's string representation.
 */
public interface DecodedJWT extends Payload, Header {
    /**
     * Getter for the String Token used to create this JWT instance.
     *
     * @return the String Token.
     */
    String getToken();

    /**
     * Getter for the Header contained in the JWT as a Base64 encoded String.
     * This represents the first part of the token.
     *
     * @return the Header of the JWT.
     */
    String getHeader();

    /**
     * Getter for the Payload contained in the JWT as a Base64 encoded String.
     * This represents the second part of the token.
     *
     * @return the Payload of the JWT.
     */
    String getPayload();

    /**
     * Getter for the Signature contained in the JWT as a Base64 encoded String.
     * This represents the third part of the token.
     *
     * @return the Signature of the JWT.
     */
    String getSignature();
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用户登录的详细流程(二)JWT生成token登录 的相关文章

  • 如何根据 JComboBox 选择动态地将控件添加到表单?

    我正在尝试使用 Swing 创建一个简单的 java 表单 这个想法的基本思想是用户将在 JComboBox 中选择 0 到 5 然后 通过 ItemStateChanged 侦听器 将动态添加几个面板 每个面板包含 4 个控件 因此 如果
  • Java - 了解 PrintWriter 和刷新的需要

    好吧 首先我对所有代码表示歉意 但我觉得代码太多总比代码不够好 我正在制作一个简单的聊天客户端和印刷机 尤其是我正在努力解决的问题 使用现在的代码 它将与服务器类交互 并且完美地打印我想要打印的内容 但是 当我删除 writer flush
  • 如何加载椭圆曲线 PEM 编码的私钥? [复制]

    这个问题在这里已经有答案了 我使用 OpenSSL 生成了椭圆曲线私钥 公钥对 私钥和公钥均采用 PEM 编码 我已经弄清楚如何加载公钥 感谢this https stackoverflow com a 40439081但是 我无法弄清楚如
  • 从 Java 启动外部进程:stdout 和 stderr

    我正在使用标准从 java 启动一个外部进程java lang Process 我试图弄清楚该过程的输出是什么 但是采用结合了两者的格式stdout and stderr 目前 我有Process getInputStream它提供了访问s
  • ORMLite - join where 子句中的括号

    我想使用连接三个表QueryBuilder join and QueryBuilder joinor但我想在 where 子句中添加括号 如下所示 WHERE first table where AND second table where
  • java模拟自定义对象

    public class MainClass public void makeCall CustomObject obj new CustomObject obj testMethod 我想进行单元测试makeCall 所以我必须嘲笑Cus
  • 带有 @Scheduled Spring 注释的方法的切入点

    我想要一个带有注释的方法的 AspectJ 切入点 Scheduled 尝试了不同的方法但没有任何效果 1 Pointcut execution org springframework scheduling annotation Sched
  • Android 防火墙与 VpnService

    我正在尝试使用 BS 项目的 VpnService 为 Android 实现一个简单的防火墙 我选择 VpnService 因为它将在非 root 设备上运行 它将记录连接并让您过滤连接 基于IP 有一个应用程序可以做到这一点 因此这是可能
  • 当用户使用相同的凭据登录两次时如何使用户会话无效

    我正在使用带有 Richfaces 和 Facelets 的 JSF 1 2 我有一个应用程序 其中包含许多会话范围的 Bean 和一些应用程序 Bean 假设用户使用 Firefox 登录 创建一个会话 ID A 然后他打开 Chrome
  • JavaFX 动画使用循环?

    我正在尝试制作一款类似太空侵略者的游戏 我画了一个正方形 我想通过使用循环逐步向下移动它thread sleep 然而 正方形立即被绘制出来 我知道有可以使用的动画路径 但我想保持低水平并仅使用坐标系 有没有办法使用这样的循环来制作时间轴动
  • Android Google 地图:隐藏整个地图的多边形或形状

    我试图隐藏除一个区域之外的整个地图 因为我使用的多边形在我想要显示的区域中有一个洞 问题在于 根据缩放的不同 空白区域会被多边形的颜色覆盖 或者多边形会失去其颜色 这是代码 polygon hide all world map float
  • Android 上的自定义视图和窗口属性

    我想要做的是在我的应用程序顶部添加一个视图 该视图类似于过滤器视图 我想操纵屏幕的颜色 并且我还希望能够同时更改屏幕的亮度时间 这两件事似乎是分开起作用的 但不能一起起作用 这是我的代码 添加视图 colourView new Layer
  • 酷还是傻? Catch(异常[NamingException, CreateException] e)

    我正在编写一些代码 我注意到异常处理中的一种模式让我思考 try do stuff throws JMS Create and NamingException catch NamingException e log1 e rollback
  • EasyMock : java.lang.IllegalStateException: 1 个匹配器预期,2 个记录

    我在使用 EasyMock 2 5 2 和 JUnit 4 8 2 通过 Eclipse 运行 时遇到问题 我已阅读此处所有类似的帖子 但尚未找到答案 我有一个包含两个测试的类 它们测试相同的方法 我正在使用匹配器 每个测试单独运行时都会通
  • 未从线程接收位置数据

    我尝试使用计时器经常发送包含用户位置的短信 最初 我遇到了空指针异常 这是由于我犯了一个简单的错误 一旦解决了这个问题 一切似乎都运行良好 但是 它永远不会获取我的位置 因此 不断发送的文本显示 无法接收位置 我想问的是为什么它无法获取我的
  • 为什么 Cassandra 客户端在生产中没有 epoll 时会失败? [复制]

    这个问题在这里已经有答案了 当我在本地运行服务时 我收到一条警告 指出 epoll 不可用 因此它使用 NIO 很公平 当我将其部署到 Kubernetes 中时 我得到了以下信息 这导致服务无法运行 2017 03 29T19 09 22
  • org.apache.catalina.core.JreMemoryLeakPreventionListener 中急切调用 URLConnection 的 setDefaultUseCaches(false) 是什么原因

    这个问题可能有点难以找到答案 这是一个系列中的问题考虑使用 Policy getPolicy 的原因是什么 因为它将保留对上下文的静态引用并可能导致内存泄漏 https stackoverflow com questions 7057421
  • Hibernate 命名查询使用 Like 和 % % 运算符?

    在我的 Hibernate JPA 示例代码中 public List
  • Java分数计算器

    我对 Java 编程还很陌生 我的 AP 计算机编程课程有作业要完成 所以请耐心等待 我必须弄清楚如何将两个分数相乘 我想知道是否有任何方法可以在方法内部声明变量并在该方法外部使用它 我在介绍方法中的 while 循环 谢谢您 希望这不会令
  • 丰富:数据表行跨度问题

    我需要创建一个 rich dataTable 甚至扩展 具有以下功能 我有一个公司类 其中包含产品对象的集合 我想展示下表 我仍然没有弄清楚如何使用子表执行此操作 在所有示例中 我发现子表具有与主表完全相同的列 据推测 我需要在前两列中使用

随机推荐

  • 数据清洗、数据挖掘常见十大问题

    数据清洗 数据挖掘常见十大问题 一 数据预处理 数据清洗和特征工程 二 数据预处理和特征工程阶段 最常见的10个问题 1 什么是数据 EDA 2 缺失值的处理方式有哪些 3 如何检测异常数据 如何处理 4 什么是特征工程 有什么作用 5 特
  • 【Spring】数据导出为Excel的接口报java.io.IOException: UT010029: Stream is closed错误

    数据导出为Excel的接口报java io IOException UT010029 Stream is closed错误 实习时导师让写一个平台信息导出为Excel的功能 写完之后发现文件正常导出 但控制台一直报Stream is clo
  • react中使用less和全局样式

    前言 使用create react app脚手架搭建的react项目 会自带css和sass 但是没有less 如果在项目中需要使用less 需要进行下载并进行一些配置 1 配置 1 暴露webpack配置文件 create react a
  • 解决 in ./node_modules/cesium/Source/ThirdParty/zip.js报错

    由于在 node modules cesium Source ThirdParty zip js 文件中使用了 import meta 语法 webpack 默认不支持 在进行项目构建时 会报如下错误 提示信息需要添加 loader 接下来
  • 谷歌浏览器配置微信浏览器_使用Chrome修改user agent模拟微信内置浏览器

    很多时候 我们需要模拟微信内置浏览器 今天教大家用chrome简单模拟 如图设置 F12或者右键审查元素进入开发者模式 点击Emulation 然后点击Network 把Spoof user agent改成Other 并把下面的带复制进去
  • PaddleSpeech调研、安装、使用

    PaddleSpeech概述 PaddleSpeech asr 模块目前只支持中英文的语音自动识别 建议在Linux环境下安装和使用 配置环境要求 gcc gt 4 8 5 paddlepaddle gt 2 4 1 python gt 3
  • 概率论与数理统计

    目录 一 概率论的基本概念 1 1 概率论的直观解释和数学定义 1 2 条件概率与乘法公式 1 3 全概率公式与贝叶斯公式 1 4 事件的独立性 二 随机变量与分布函数 2 1 随机变量与分布函数 2 2 离散型随机变量和常用分布 2 3
  • 定时任务——Cron表达式详解

    Cron表达式是一个字符串 字符串以5或6个空格隔开 分为6或7个域 每一个域代表一个含义 Cron有如下两种语法格式 Seconds Minutes Hours DayofMonth Month DayofWeek Year或 Secon
  • C++ : 在一个string字符串中查找给定的字符串并提取

    C 在一个string字符串中查找给定的字符串并提取 1 string find last of 返回类型 size t 2 string find first of 返回类型 size t 3 string substr size t a
  • 力扣刷题-面试题 17.13. 恢复空格、字典树、前缀树的应用

    基本概念 Trie 树 又称单词查找树 前缀树 是一种树形结构 典型应用是用于统计 排序和保存大量的字符串 但不仅限于字符串 它的优点是 利用字符串的公共前缀来减少查询时间 最大限度地减少无谓的字符串比较 比哈希表更快 基本性质 根节点不包
  • 正负样本分配策略(OTA, SimOTA,TAS)

    文章目录 OTA SimOTA TAL ATSS OTA 论文 OTA Optimal Transport Assignment for Object Detection 代码 Megvii BaseDetection OTA 标签分配算法
  • c++静态代码扫描工具clang-tidy详细介绍

    clang tidy 文章目录 clang tidy 1 什么是clang tidy 2 clang tidy可以解决什么问题 3 工作原理 4 如何使用clang tidy 4 总结 5 举例说明 1 什么是clang tidy Clan
  • 十五年学不会英语的原因

    学习前预热 轻松学英语第一步 建立英语思维 为什么大家学英语学得这么累 最后依然对英语糊糊涂涂 原因只有一个 就是我们的学习能力太差了 我们的老师太笨了 这篇文章主要是给大家讲英语的基本结构 看了这篇文章 你们会突然就明白 英语怎么会如此简
  • 第19章:python自动化——ChromeOptions与WebUI实操

    目录 一 ChromeOptions设置项 二 WebUI实操 一 ChromeOptions设置项 浏览器在启动之初 如果需要对浏览器进行一些特定内容的定义 可以直接通过浏览器的options类来实现相对应的配置内容 不同的浏览器有不同的
  • Vue中如何配置自定义路径别名

    Vue中如何配置自定义路径别名 在我们日常开发中 常常会导入一些模块或者组件 如果采用相对路径的方式 import uEditor from components tools 会显得臃肿 多余 如果引用稍有差错就会出现 404的报错 不优雅
  • A Survey on Large Language Model based Autonomous Agents

    本文是LLM系列的文章 针对 A Survey on Large Language Model based Autonomous Agents 的翻译 基于大模型的自动agents综述 摘要 1 引言 2 基于LLM的自动代理构建 3 基于
  • 学网络安全都是一群什么人?

    大家好呀 我是知了姐 又是一期学员故事栏目 3月下旬知了堂信安方向开新班 知了姐跟着去采访 了解到新学员们的求学故事 嘿你别说 虽然大家出身专业不同 经历背景不同 如今却在同一个地点相遇 加入到知了堂这个大家庭 不同专业 年龄的他们 为什么
  • 格式工厂5.10.0版本安装

    目前格式工厂有很多 大多都可以进行视频转换 之前遇到一个用ffmpeg拉流保存的MP4在vlc和迅雷都无法正常播放的问题 发现视频长度不对 声音也不对 最后换到了格式工厂的格式播放器是可以正常播放的 格式工厂下载之家的地址 https ww
  • OSG for Android新手教程系列(二)——项目配置

    在上一篇教程中 主要介绍了如何把OSG源代码编译成为能够在Android项目下使用的函数库 在这一篇教程中 我将针对如何在自己的Android项目中配置OSG函数库进行详细讲解 现阶段网上关于OSGfor Android的配置方式教程有很多
  • 用户登录的详细流程(二)JWT生成token登录

    JWT生成token登录 1 jwt的构成 1 header 2 payload 3 signature 2 token的登陆原理 3 在实际中如何应用token 1 设置token的生成代码 2 如何从token中获取有用的信息 3 验证