当前位置: 首页 > news >正文

双Token方案实现Token自动续期(基于springboot+vue前后端分离项目)

文章目录

  • 前言
  • 一、双Token方案介绍
    • 1. 令牌类型与功能
    • 2.双Token方案的优点
    • 3.实现流程
  • 二、具体实现
    • 1.后端实现
      • 1.1 jwt工具类
      • 1.2 响应工具类
      • 1.3 实体类
      • 1.4 过滤器
      • 1.5 controller
      • 1.6 启动类
    • 2、前端实现
      • 2.1 登录页面
      • 2.2 index页面
      • 2.3 请求拦截器和响应拦截器
  • 效果展示


前言

更多jwt相关文章:
jwt理论介绍
springboot+vue项目中使用jwt实现登录认证

本篇文章的代码是在springboot+vue项目中使用jwt实现登录认证的基础上实现的Token自动续期的功能。


一、双Token方案介绍

双token解决方案是一种用于增强用户登录安全性和提升用户体验的认证机制。它主要涉及两个令牌:访问令牌(accessToken)和刷新令牌(refreshToken)。以下是对双token解决方案的详细介绍:

1. 令牌类型与功能

  • 访问令牌(accessToken):
    有效期较短,通常设置为较短的时间,如两小时或根据业务需求自定义(如10分钟)。 储存用户信息权限等,包含用户相关信息,如UserID、Username等。 用于前端与后端之间的通信认证,前端在每次请求时携带此令牌进行校验。
  • 刷新令牌(refreshToken):
    有效期较长,可以设置为一星期、一个月或更长时间,具体根据业务需求自定义。 不储存额外信息,只储存用户id,用于在accessToken过期后重新生成新的accessToken。 由于有效期长,因此降低了用户需要频繁登录的频率。
  • 2.双Token方案的优点

  • 增强安全性:通过短期有效的accessToken和长期有效的refreshToken的结合,即使accessToken泄露,攻击者也只能在有限时间内进行模拟用户行为,降低了安全风险。
  • 提升用户体验:由于refreshToken的存在,用户无需频繁登录,特别是在长时间操作或后台服务场景下,提高了用户体验。
  • 3.实现流程

  • 登录:用户输入用户名和密码进行登录,后端验证成功后生成accessToken和refreshToken,并发送给前端。
  • 请求校验:前端在每次请求时携带accessToken进行校验,如果accessToken有效,则允许请求继续;如果无效但refreshToken有效,则使用refreshToken重新生成accessToken。
  • 令牌刷新:当accessToken过期但refreshToken未过期时,前端可以使用refreshToken向后端请求新的accessToken,无需用户重新登录。
  • 登出:用户登出时,后端需要同时使accessToken和refreshToken失效,以确保用户登出后的安全性。
  • 二、具体实现

    1.后端实现

    1.1 jwt工具类

    package com.etime.util;import io.jsonwebtoken.*;import java.util.Date;
    import java.util.Map;
    import java.util.UUID;/*** @Date 2024/6/10 10:04* @Author liukang**/
    public class JwtUtil {
    //    private static long expire = 1000*60*5;// 单位是毫秒private static String secret = "secret";/*** 创建jwt* @author liukang* @date 10:36 2024/6/10* @param expire* @param map* @return java.lang.String**/public static String generateToken(long expire, Map map){// 床jwt构造器JwtBuilder jwtBuilder = Jwts.builder();// 生成jwt字符串String jwt = jwtBuilder//头部.setHeaderParam("typ","JWT").setHeaderParam("alg","HS256")// 载荷.setClaims(map) // 设置多个自定义数据  位置只能放在前面,如果放在后面,那前面的载荷会失效.setId(UUID.randomUUID().toString())// 唯一标识.setIssuer("liukang")// 签发人.setIssuedAt(new Date())// 签发时间.setSubject("jwtDemo")// 主题.setExpiration(new Date(System.currentTimeMillis()+expire))//过期时间// 自定义数据
    //                .claim("uname","liukang")// 签名.signWith(SignatureAlgorithm.HS256,secret).compact();return jwt;}/*** 创建jwt* @author liukang* @date 10:36 2024/6/10* @param expire* @return java.lang.String**/public static String generateToken(long expire){// 床jwt构造器JwtBuilder jwtBuilder = Jwts.builder();// 生成jwt字符串String jwt = jwtBuilder//头部.setHeaderParam("typ","JWT").setHeaderParam("alg","HS256")// 载荷.setId(UUID.randomUUID().toString())// 唯一标识.setIssuer("liukang")// 签发人.setIssuedAt(new Date())// 签发时间.setSubject("jwtDemo")// 主题.setExpiration(new Date(System.currentTimeMillis()+expire))//过期时间// 自定义数据
    //                .claim("uname","liukang")// 签名.signWith(SignatureAlgorithm.HS256,secret).compact();return jwt;}/*** 解析jwt* @author liukang* @date 10:36 2024/6/10* @param jwt* @return io.jsonwebtoken.Claims**/public static Claims parseToken(String jwt){Jws<Claims> claimsJws = Jwts.parser().setSigningKey(secret).parseClaimsJws(jwt);Claims playload = claimsJws.getBody();return playload;}
    }

    1.2 响应工具类

    代码如下(示例):

    package com.etime.util;import com.etime.vo.ResponseModel;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.http.MediaType;import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;/*** @Date 2024/6/10 10:00* @Author liukang**/
    public class ResponseUtil {public static void write(ResponseModel rm, HttpServletResponse response) throws IOException {// 构造响应头response.setContentType(MediaType.APPLICATION_JSON_VALUE);response.setCharacterEncoding("utf-8");// 解决跨域问题 设置跨域头response.setHeader("Access-Control-Allow-Origin","*");// 输出流PrintWriter out = response.getWriter();// 输出out.write(new ObjectMapper().writeValueAsString(rm));// 关闭流out.close();}
    }

    1.3 实体类

    登录用户实体类

    package com.etime.entity;import lombok.Data;/*** @Date 2024/6/10 10:39* @Author liukang**/
    @Data
    public class User {private String username;private String password;
    }

    响应vo类

    package com.etime.vo;import lombok.Data;import java.util.Objects;/*** @Date 2024/6/10 10:37* @Author liukang**/
    @Data
    public class ResponseModel {private Integer code;private String msg;private Object token;public ResponseModel(Integer code, String msg, Object token) {this.code = code;this.msg = msg;this.token = token;}
    }

    1.4 过滤器

    package com.etime.filter;import com.etime.util.JwtUtil;
    import com.etime.util.ResponseUtil;
    import com.etime.vo.ResponseModel;
    import com.sun.deploy.net.HttpResponse;
    import org.springframework.http.HttpMethod;
    import org.springframework.http.HttpRequest;
    import org.springframework.util.StringUtils;import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;/*** @Description jwt过滤器* @Date 2024/6/10 9:46* @Author liukang**/
    @WebFilter(urlPatterns = "/*") // 过滤所有路径
    public class JwtFilter implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {// 得到两个对象HttpServletRequest request =  (HttpServletRequest) servletRequest;HttpServletResponse response =  (HttpServletResponse) servletResponse;//直接放行if(HttpMethod.OPTIONS.toString().equals(request.getMethod())){filterChain.doFilter(request,response);return;}String requestURI = request.getRequestURI(); // 不含主机和端口号if(requestURI.contains("/login")){filterChain.doFilter(request,response);return;}// 得到请求头的信息(accessToken)String token = request.getHeader("accessToken");if(!StringUtils.hasText(token)){//响应前端错误的消息提示ResponseModel responseModel = new ResponseModel(500,"failure","令牌缺失!");ResponseUtil.write(responseModel,response);return;}// 解析Token信息try {JwtUtil.parseToken(token);}catch (Exception e){//响应前端错误的消息提示ResponseModel responseModel = new ResponseModel(401,"failure","令牌过期!");ResponseUtil.write(responseModel,response);return;}filterChain.doFilter(request,response);}
    }

    1.5 controller

    登录Controller

    package com.etime.controller;import com.etime.entity.User;
    import com.etime.util.JwtUtil;
    import com.etime.vo.ResponseModel;
    import org.springframework.web.bind.annotation.*;import java.util.HashMap;
    import java.util.Map;/*** @Date 2024/6/10 10:38* @Author liukang**/
    @RestController
    @CrossOrigin
    public class LoginController {@PostMapping("/login")public ResponseModel login(@RequestBody User user){Integer code = 200;String msg = "success";String accessToken = null;String refreshToken = null;Map tokenMap = new HashMap();if(user.getUsername().equals("admin")&&user.getPassword().equals("123")){// 生成jwtaccessToken = JwtUtil.generateToken(1000*10);// 设置有效期为10srefreshToken = JwtUtil.generateToken(1000*30);// 设置有效期为30stokenMap.put("accessToken",accessToken);tokenMap.put("refreshToken",refreshToken);}else {code = 500;msg = "failure";}return new ResponseModel(code,msg,tokenMap);}}

    测试请求Controller

    package com.etime.controller;import com.etime.vo.ResponseModel;
    import org.springframework.web.bind.annotation.CrossOrigin;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RestController;/*** @Date 2024/6/10 12:51* @Author liukang**/
    @CrossOrigin
    @RestController
    public class TestController {@PostMapping("/test")public ResponseModel test() {return new ResponseModel(200,"success","测试请求接口成功!");}}

    刷新Token的Controller

    package com.etime.controller;import com.etime.util.JwtUtil;
    import com.etime.vo.ResponseModel;
    import org.springframework.web.bind.annotation.CrossOrigin;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
    import java.util.Map;/*** @Date 2024/6/10 15:48* @Author liukang**/
    @CrossOrigin
    @RestController
    public class NewTokenController {@GetMapping("/newToken")public ResponseModel newToken(){String accessToken = JwtUtil.generateToken(1000*10);String refreshToken = JwtUtil.generateToken(1000*30);Map tokenMap = new HashMap();tokenMap.put("accessToken",accessToken);tokenMap.put("refreshToken",refreshToken);return new ResponseModel(200,"success",tokenMap);}
    }

    1.6 启动类

    package com.etime;import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.web.servlet.ServletComponentScan;/*** @Author liukang* @Date 2022/7/4 11:32*/
    @SpringBootApplication
    @ServletComponentScan(basePackages = "com.etime.filter")// 这个包下激活WebFilter这个注解
    public class Application {public static void main(String[] args) {SpringApplication.run(Application.class);}
    }

    2、前端实现

    2.1 登录页面

    <template><div class="hello"><form>用户名:<input v-model="username"/><br>密码<input v-model="password" /><br><button @click="login">登录</button></form></div></template><script>export default {data () {return {username:'',password:'',}},methods:{login(){this.axios.post('http://localhost:8088/login',{username:this.username,password:this.password,}).then(response => {console.log(response.data);if(response.data.code==200){sessionStorage.setItem("accessToken",response.data.token.accessToken)sessionStorage.setItem("refreshToken",response.data.token.refreshToken)this.$router.push({ path: 'index'});}}).catch(error => {console.error(error);});}},}</script><style scoped></style>

    2.2 index页面

    <template><div><button @click="test">请求受保护的接口</button></div></template><script>
    import intercepterConfig from './js/config'export default {data () {return {}},methods:{test(){const accessToken = sessionStorage.getItem('accessToken')let token = nullif(accessToken){token = accessToken}// console.log(token)this.axios.post('http://localhost:8088/test',{},/*{headers:{accessToken:'token'}}*/).then(response => {// if(response.data.code==200){console.log(response.data);// }}).catch(error => {console.error(error);});},},}</script><style scoped></style>

    2.3 请求拦截器和响应拦截器

    import axios from "axios";
    //axios请求拦截器
    axios.interceptors.request.use(config=>{// 正确的请求拦截器let token = null;let url = config.url// url.indexOf('/newToken')==-1  如果是刷新Token的请求 不用在拦截器里面加accessToken 这个请求已经在请求头中设置accessToken,加了会覆盖if(sessionStorage.getItem('accessToken')!=null && url.indexOf('/newToken')==-1){token = sessionStorage.getItem('accessToken')config.headers['accessToken'] = token}// 加入头信息的配置return config // 这句没写请求会发不出去},error=>{ // 出现异常的请求拦截器return Promise.reject(error)})
    // axios响应拦截器
    axios.interceptors.response.use(async res => {// 判断 401状态码 自动续期if (res.data.code == 401 &&!res.config.isRefresh) {//!res.config.isRefresh  不是刷新Token的请求才拦截 是则不拦截// 1.自动续期const res2 = await getNewToken()if(res2.data.code == 200){console.log('自动续期成功'+new Date().toLocaleString())// 2.更新sessionStorage里面的Token   没有这一步会死循环sessionStorage.setItem('accessToken',res2.data.token.accessToken)sessionStorage.setItem('refreshToken',res2.data.token.refreshToken)//3.重新发送请求res = await axios.request(res.config)// res.config 代表请求的所有参数(这里是上一次请求的所有参数),包括url和携带的所有数据}}return res     // 将重新请求的响应作为响应返回},error=>{return Promise.reject(error)})function getNewToken(){let url = "http://localhost:8088/newToken"let token = nullif(sessionStorage.getItem('refreshToken')!=null){token = sessionStorage.getItem('refreshToken')}return  axios.get(url,{headers:{accessToken:token},isRefresh:true})// 注意这里参数是accessToken:token  因为后端过滤器里面获取的是accessToken,所以要写这个,不然过滤器通不过过滤器
    }

    效果展示

    1.登录页面
    在这里插入图片描述
    2.输入用户名和密码点击【登录】
    在这里插入图片描述
    3.点击【请求受保护的资源】按钮
    在这里插入图片描述
    3.等待10秒,accessToken过期,但refreshToken未过期时,点击【请求受保护的资源】按钮
    在这里插入图片描述
    4.等待30秒后,refreshToken和accessToken都过期,再次点击【请求受保护的资源】按钮

    在这里插入图片描述


相关文章:

双Token方案实现Token自动续期(基于springboot+vue前后端分离项目)

文章目录 前言一、双Token方案介绍1. 令牌类型与功能2.双Token方案的优点3.实现流程 二、具体实现1.后端实现1.1 jwt工具类1.2 响应工具类1.3 实体类1.4 过滤器1.5 controller1.6 启动类 2、前端实现2.1 登录页面2.2 index页面2.3 请求拦截器和响应拦截器 效果展示 前言 更多j…...

别太小看“静态免杀“

0x01 简述 免杀总体来说可分为两种&#xff0c;静态免杀/动态免杀。往往来说&#xff0c;我们更注重于在内部代码层面实现一些免杀技巧&#xff0c;但在有些时候&#xff0c;动态免杀静态免杀以"打组合拳"的方式效果往往会更出人所料。 当我们的程序生成后&#xf…...

SQL server 内连接 左连接 右连接 全连接 语句

在SQL Server中&#xff0c;连接&#xff08;JOIN&#xff09;操作用于从两个或多个表中检索相关数据。内连接、左连接、右连接和全连接是最常用的几种连接类型。下面详细介绍每种连接的用法和区别&#xff1a; 1. 内连接 (INNER JOIN) 内连接只返回两个表中满足连接条件的匹…...

k8s中的pod域名解析失败定位案例

问题描述 我在k8s中启动了一个Host网络模式的pod&#xff0c;这个pod的域名解析失败了。 定位步骤 敲kubectl exec -it [pod_name] -- bash进入pod后台&#xff0c;查看/etc/resolv.conf&#xff0c;发现nameserver配的有问题。这里我预期的nameserver应该使用宿主机的&…...

jingxiang制作

文章目录 jingxiang制作为什么需要jingxiang制作如何进行jingxiang制作 快照方式制作jingxiang制作命令do cker commit 快照制作jingxiang创建临时工作目录编写一个实例代码启动一个容器替换国内软件源安装编译软件源代码拷贝到容器中编译运行提交为一个jingxiang测试是否可以正…...

【数据结构】线性表之《顺序表》超详细实现

顺序表 一.数据结构1.逻辑结构2.物理结构 二.顺序表的分类1.静态顺序表2.动态顺序表 三.顺序表的实现1.创建顺序表2.初始化顺序表3.判断是否扩容4.打印顺序表5.插入操作1.头插2.尾插3.按照下标插入 6.删除操作1.头删2.尾删3.按照下标删除 7.查找数据8.修改数据9.清空顺序表10.销…...

开源模型应用落地-音乐生成模型-suno/bark深度使用-AIGC应用探索(六)

一、前言 学习音乐生成模型具有极其重要的价值。通过对音乐生成模型的深入学习,我们能够探索到音乐创作的全新边界和可能性。它不仅可以开启一扇通往无限音乐创意的大门,让我们领略到科技与艺术完美融合所带来的震撼与惊喜,还能帮助我们在音乐领域实现前所未有的突破和创新。…...

为何选择Xinstall?告别邀请码,让App推广更便捷!

在互联网日益繁荣的今天&#xff0c;App的推广和运营成为了各大企业关注的重点。然而&#xff0c;传统的推广方式如邀请码限制&#xff0c;往往会给用户带来不便&#xff0c;同时也限制了App的快速增长。在这个背景下&#xff0c;Xinstall凭借其独特的功能和服务&#xff0c;成…...

JavaScript基础入门

目录 任务描述 相关知识 JavaScript语言简介 JavaScript注释 搭建JavaScript的运行环境 JavaScript输出 弹出对话框模式 控制台模式 页面输出模式 编程要求 任务描述 要了解一门编程语言&#xff0c;要从输出开始。 本关任务&#xff1a;采用相关知识中介绍的任意一…...

windows11子系统Ubuntu 22.04.4子安装图形化界面

1、windows11家庭版本设置 打开虚拟机安装许可 2、Microsoft Store下载安装ubuntu 我使用的是22.04.4 LTS版本 3、 打开ubuntu 命令窗口 1、打开win11的命令行&#xff0c;在下拉三角下标&#xff0c;打开&#xff0c;可以看到有Ubuntu 的选项&#xff0c;点击即可进入linux命…...

对 2024 年美赛选题的建议

对2024年美赛选题的建议包括&#xff1a; 1. 深入探讨当下全球面临的重大问题和挑战&#xff1a;鉴于美赛通常聚焦于全球性议题&#xff0c;如气候变化、可持续发展、数据分析等&#xff0c;参赛学生应关注这些议题&#xff0c;并深入研究相关数据与背景信息&#xff0c;以提出…...

PyTorch tutorials:快速学会使用PyTorch

准备深入学习transformer&#xff0c;并参考一些资料和论文实现一个大语言模型&#xff0c;顺便做一个教程&#xff0c;今天是番外篇&#xff0c;介绍下PyTorch&#xff0c;后面章节实现代码主要使用这个框架。 本系列禁止转载&#xff0c;主要是为了有不同见解的同学可以方便联…...

【CT】LeetCode手撕—手撕快排

目录 题目1-思路-快排1-1 快排的核心思想快速排序算法步骤优美的调整区间 1-2 ⭐快排的实现 2- 实现⭐912. 排序数组——题解思路 3- ACM 实现 题目 原题连接&#xff1a;912. 排序数组 1-思路-快排 1-1 快排的核心思想 选择一个基准 基准左侧的元素都小于该元素基准右侧的元…...

使用ARK工具ATool清除典型蠕虫MyDoom

1 概述 在长期的日常安全事件监测过程中&#xff0c;安天CERT经常捕获到大量的MyDoom蠕虫样本和传播该蠕虫的钓鱼邮件。受害主机感染MyDoom后会被放置后门&#xff0c;以便攻击者下发后续恶意软件&#xff0c;进行攻击或窃密等操作。MyDoom蠕虫最早发现于2004年&…...

在hue中使用ooize调度ssh任务无法执行成功,无法查看错误

ssh执行失败&#xff0c;但是hue没有给出明确的错误原因&#xff1a; 经过经验分析&#xff0c;原来是服务器上的sh文件用的是doc/window格式&#xff0c;需要使用notepad将格式改为unix之后就可以正常执行。 特此记录&#xff0c;避免遗忘知识点...

一套轻量、安全的问卷系统基座,提供面向个人和企业的一站式产品级解决方案

大家好&#xff0c;今天给大家分享的是一款轻量、安全的问卷系统基座。 XIAOJUSURVEY是一套轻量、安全的问卷系统基座&#xff0c;提供面向个人和企业的一站式产品级解决方案&#xff0c;快速满足各类线上调研场景。 内部系统已沉淀 40种题型&#xff0c;累积精选模板 100&a…...

3秒生成!这个AI模型画风也太治愈了,新手也能轻松驾驭

还在为不会画画而苦恼吗&#xff1f;别担心&#xff0c;今天给大家介绍一个超好用的AI模型——Soft and Squishy Linework&#xff0c;即使是小白也能轻松生成可爱的动漫图像&#xff01; Soft and Squishy Linework&#xff1a;专门生成柔和的、低保真&#xff08;lofi&#…...

数字人全拆解:如何构建一个基于大模型的实时对话3D数字人?

简单地说&#xff0c;数字人就是在数字世界的“人”。当前语境下我们谈到的数字人通常指的是借助AI技术驱动的虚拟世界人物&#xff0c;具备与真实人类相似甚至接近的外形、感知、交互与行为能力。 AI技术在智能数字人的应用中举足轻重&#xff0c;特别是随着大模型能力的涌现…...

实战 | 基于YOLOv10的车辆追踪与测速实战【附源码+步骤详解】

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…...

2024北京智源大会

北京智源大会是年度国际性人工智能高端学术交流的盛会&#xff0c;定位于内行的AI盛会。智源大会紧密围绕当前人工智能学术领域迫切需要解决的问题&#xff0c;以及产业落地过程中存在的诸多挑战&#xff0c;开展深入探讨。智源研究院是2018年11月份成立的一家人工智能领域的新…...

youlai-boot项目的学习—本地数据库安装与配置

数据库脚本 在项目代码的路径下&#xff0c;有两个版本的mysql数据库脚本&#xff0c;使用对应的脚本就安装对应的数据库版本&#xff0c;本文件选择了5 数据库安装 这里在iterm2下使用homebrew安装mysql5 brew install mysql5.7注&#xff1a;记得配置端终下的科学上网&a…...

Android平台如何实现多路低延迟RTSP|RTMP播放?

技术背景 实际上&#xff0c;我们在2015年做Android平台RTSP、RTMP播放模块的时候&#xff0c;第一版就支持了多实例播放&#xff0c;因为SDK设计比较灵活&#xff0c;做个简单的player实例封装即可实现多实例播放&#xff08;Android Unity的就有多路demo&#xff09;&#x…...

深入探索Java开发世界:Java基础~类型分析大揭秘

文章目录 一、基本数据类型二、封装类型三、类型转换四、集合类型五、并发类型 Java基础知识&#xff0c;类型知识点梳理~ 一、基本数据类型 Java的基本数据类型是语言的基础&#xff0c;它们直接存储在栈内存中&#xff0c;具有固定的大小和不变的行为。 八种基本数据类型的具…...

短URL服务设计

引言 在营销系统里&#xff0c;为了增加系统的活跃用户数&#xff0c;经常会有各种各样的营销活动。这类活动几乎都是为了充分利用存量用户的价值&#xff0c;促使他们分享产品或App以达到触达到更多用户的目的。又或者是出于营销目的&#xff0c;群发优惠券触达短信这种场景。…...

Kafka集成flume

1.flume作为生产者集成Kafka kafka作为flume的sink&#xff0c;扮演消费者角色 1.1 flume配置文件 vim $kafka/jobs/flume-kafka.conf # agent a1.sources r1 a1.sinks k1 a1.channels c1 c2# Describe/configure the source a1.sources.r1.type TAILDIR #记录最后监控文件…...

如何让视频有高级感 高级感视频制作方法 高级感视频怎么剪 会声会影视频剪辑制作教程 会声会影中文免费下载

高质量视频通常具有清晰的画面、优质的音频和令人印象深刻的视觉效果。这篇文章来了解如何让视频有高级感&#xff0c;高级感视频制作方法。 一、如何让视频有高级感 要让视频有高级感&#xff0c;要注意以下几个要点&#xff1a; 1、剧本和故事性&#xff1a;一个好的剧本和…...

详解|访问学者申请被拒原因有哪些?

访问学者项目为全球科研人员提供了一个难得的机会&#xff0c;让他们能够跨越国界&#xff0c;深入不同的学术环境&#xff0c;进行学术交流和合作。然而&#xff0c;并非所有申请者都能如愿以偿地获得这一机会。本文将对访问学者申请中常见的被拒原因进行详细解析&#xff0c;…...

[鹤城杯 2021]BabyRSA

题目&#xff1a; from Crypto.Util.number import getPrime, bytes_to_long from secret import flagp getPrime(1024) q getPrime(1024) n p * q e 65537 hint1 p >> 724 hint2 q % (2 ** 265) ct pow(bytes_to_long(flag), e, n) print(hint1) print(hint2) p…...

西安市工业倍增引导基金子基金申报条件流程和材料程序指南(2024年)

一、基本情况 产业投资基金是以产业发展为首要目标&#xff0c;围绕经济社会发展规划和产业发展政策&#xff0c;发挥“有效市场”作用&#xff0c;支持重点领域、重点产业、重点区域&#xff08;如&#xff1a;全市六大支柱产业、五大新兴产业领域成熟期重点规模以上企业以及“…...

微型丝杆的耐用性和延长使用寿命的关键因素!

无论是机械设备&#xff0c;还是精密传动元件&#xff0c;高精度微型丝杆是各种机械设备中不可或缺的重要组件。它的精度和耐用性直接影响着工作效率和产品品质&#xff0c;在工业技术不断进步的情况下&#xff0c;对微型丝杆的性能要求也越来越高&#xff0c;如何提升微型丝杆…...

开源网站系统/网站关键词排名分析

作者 | 屠敏出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;日前&#xff0c;TIOBE 编程语言社区最新发布了 2019 年 5 月排行榜。和 4 月榜单相比&#xff0c;5 月编程语言排行榜的 Top 10 位置并没有太大变化。但是在 C 和 Python 激烈的竞争局势下&#xff0c;随…...

婚纱摄影网站首页/经典网络营销案例

二、操作系统应用41.请在考生文件夹下完成如下操作&#xff1a;(1)在考生文件夹下建立“计算机基础练习”文件夹;(2)在“计算机基础练习”文件夹下建立“文字”﹑“图片”和“多媒体”三个子文件夹;(3)在考生文件夹下查找一个名为“1.BMP”的图片文件&#xff0c;将它复制到“图…...

怎么做文学动漫网站/赚钱软件

不久后又是金九银十晒薪资的又多了起来&#xff0c;有服务员、工人、护士、教师还有“程序猿”。互联网成为了21世纪的一个新物种&#xff0c;不仅使工作轻松&#xff0c;收入也相当可观&#xff0c;这就引起了大量的互联网新人加入。程序员这类技术工种在大多数人眼里都是“高…...

做购物平台网站 民治/怎样推广小程序平台

这两天公司成立了go语言学习兴趣小组&#xff0c;慕名参与了学习。目前对于go是0基础&#xff0c;只知道它可以做高并发、效率快、编译简单、母语是C. go的安装有多种形式&#xff0c;编译安装是比较慢的一个&#xff0c;今天我就记录一下学习go编译安装流程。 1、下载软件包 h…...

哈尔滨做平台网站平台公司/网站搜索排名靠前

Java压缩解压缩文件的方法有&#xff0c;第一中借助java jdk自带的ZipOutputStream和ZipInputStream。 第二种&#xff0c;借助第三方jar&#xff0c; 例如Apache Commons Compress和Ant。 下面以Ant为例详细介绍。 前提&#xff0c;需要将Ant的ant.jar和ant-launcher.jar添加…...

嘉兴网站建设技术开发/免费域名注册

package java.util;import java.util.function.Predicate; import java.util.stream.Stream; import java.util.stream.StreamSupport;/***1.Collection接口是集合继承关系中的根接口(root interface),有些集合允许重复元素&#xff0c; * 有些集合有序&#xff0c;JDK不提供…...