理解Web登录机制:会话管理与跟踪技术解析(一)

在这篇博客中,我们将深入探讨登录校验、会话技术和会话跟踪技术的基本概念、实现原理及其在Web应用中的应用。我们将介绍常见的会话跟踪技术,如Cookies、Session,并讨论它们的优缺点。同时,我们也会涉及如何使用现有的技术栈来实现安全的登录认证和会话管理,确保用户数据的安全性和隐私性。

文章目录

前言

登录功能 

接口文档

思路分析

功能开发

测试

登录校验

会话技术

会话技术介绍

会话跟踪方案

方案一Cookie

方案二Session

方案三 令牌技术

总结


前言

在这篇博客中,我们将深入探讨登录校验、会话技术和会话跟踪技术的基本概念、实现原理及其在Web应用中的应用。我们将介绍常见的会话跟踪技术,如Cookies、Session,并讨论它们的优缺点。同时,我们也会涉及如何使用现有的技术栈来实现安全的登录认证和会话管理,确保用户数据的安全性和隐私性。


提示:以下是本篇文章正文内容,下面案例可供参考

登录功能 

在登录界面中,我们可以输入用户的用户名以及密码,然后点击 "登录" 按钮就要请求服务器,服务端判断用户输入的用户名或者密码是否正确。如果正确,则返回成功结果,前端跳转至系统首页面。 

接口文档

请求路径:/login
请求方式:POST
接口描述:该接口用于员工登录Tlias智能学习辅助系统,登录完毕后,系统下发
JWT令牌。

请求参数
参数格式:application/json
参数说明:

名称类型是否必须 备注
usernamestring 必须用户名
passwordstring必须密码

请求数据样例:

{
    "username": "jinyong",
    "password": "123456"
}

响应数据样例:

{
"code": 1,
"msg": "success",
"data":
"eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoi6YeR5bq4IiwiaWQiOjEsInVzZXJuYW1l
IjoiamlueW9uZyIsImV4cCI6MTY2MjIwNzA0OH0.KkUc_CXJZJ8Dd063eImx4H9Ojf
rr6XMJ-yVzaWCVZCo"
}

思路分析

 

登录服务端的核心逻辑就是:接收前端请求传递的用户名和密码 ,然后再根据用户名和密码查询用户信息,如果用户信息存在,则说明用户输入的用户名和密码正确。如果查询到的用户不存在,则说明用户输入的用户名和密码错误。

功能开发

LoginController

@RestController
public class LoginController {
    @Autowired
    private EmpService empService;
    @PostMapping("/login")
    public Result login(@RequestBody Emp emp){
        Emp e = empService.login(emp);
     return e != null ? Result.success():Result.error("用户名或密
    码错误");
     }
}

EmpService

public interface EmpService {
    /**
    * 用户登录
    * @param emp
    * @return
    */
    public Emp login(Emp emp);
    //省略其他代码...
}

EmpServiceImpl

@Slf4j
@Service
public class EmpServiceImpl implements EmpService {
    @Autowired
    private EmpMapper empMapper;
    @Override
    public Emp login(Emp emp) {
        //调用dao层功能:登录
        Emp loginEmp = empMapper.getByUsernameAndPassword(emp);
    //返回查询结果给Controller
    return loginEmp;
     } 
    //省略其他代码...
}

EmpMapper

@Mapper
public interface EmpMapper {
    @Select("select id, username, password, name, gender, image,
    job, entrydate, dept_id, create_time, update_time " +
    "from emp " +
    "where username=#{username} and password =#{password}")
    public Emp getByUsernameAndPassword(Emp emp);
    //省略其他代码...
}

测试

功能开发完毕后,我们就可以启动服务,打开postman进行测试了。
发起POST请求,访问:http://localhost:8080/login


 

登录校验

 我们已经完成了基础登录功能的开发与测试,在我们登录成功后就可以进入到后台管理系统中进行数据的操作。
但是当我们在浏览器中新的页面上输入地址: http://localhost:9528/#/system/dept ,发现没有
登录仍然可以进入到后端管理系统页面。

而真正的登录功能应该是:登陆后才能访问后端系统页面,不登陆则跳转登陆页面进行登陆。

为什么会出现这个问题?其实原因很简单,就是因为针对于我们当前所开发的部门管理、员工管理以及文件上传等相关接口来说,我们在服务器端并没有做任何的判断,没有去判断用户是否登录了。所以无论用户是否登录,都可以访问部门管理以及员工管理的相关数据。所以我们目前所开发的登录功能,它只是徒有其表。而我们要想解决这个问题,我们就需要完成一步非常重要的操作:登录校验。

什么是登录校验?

  • 所谓登录校验,指的是我们在服务器端接收到浏览器发送过来的请求之后,首先我们要对请求进行校验。先要校验一下用户登录了没有,如果用户已经登录了,就直接执行对应的业务操作就可以了;如果用户没有登录,此时就不允许他执行相关的业务操作,直接给前端响应一个错误的结果,最终跳转到登录页面,要求他登录成功之后,再来访问对应的数据。

了解完什么是登录校验之后,接下来我们分析一下登录校验大概的实现思路。

首先我们在宏观上先有一个认知:
前面在讲解HTTP协议的时候,我们提到HTTP协议是无状态协议。什么又是无状态的协议?
所谓无状态,指的是每一次请求都是独立的,下一次请求并不会携带上一次请求的数据。而浏览器与服务器之间进行交互,基于HTTP协议也就意味着现在我们通过浏览器来访问了登陆这个接口,实现了登陆的操作,接下来我们在执行其他业务操作时,服务器也并不知道这个员工到底登陆了没有。因为HTTP协议是无状态的,两次请求之间是独立的,所以是无法判断这个员工到底登陆了没有。

那应该怎么来实现登录校验的操作呢?具体的实现思路可以分为两部分:

  • 在员工登录成功后,需要将用户登录成功的信息存起来,记录用户已经登录成功的标记。
  • 在浏览器发起请求时,需要在服务端进行统一拦截,拦截后进行登录校验。

想要判断员工是否已经登录,我们需要在员工登录成功之后,存储一个登录成功的标记,接下来在每一个接口方法执行之前,先做一个条件判断,判断一下这个员工到底登录了没有。如果是登录了,就可以执行正常的业务操作,如果没有登录,会直接给前端返回一个错误的信息,前端拿到这个错误信息之后会自动的跳转到登录页面。
我们程序中所开发的查询功能、删除功能、添加功能、修改功能,都需要使用以上套路进行登录校验。此时就会出现:相同代码逻辑,每个功能都需要编写,就会造成代码非常繁琐。
为了简化这块操作,我们可以使用一种技术:统一拦截技术。
通过统一拦截的技术,我们可以来拦截浏览器发送过来的所有的请求,拦截到这个请求之后,就可以通过请求来获取之前所存入的登录标记,在获取到登录标记且标记为登录成功,就说明员工已经登录了。如果已经登录,我们就直接放行(意思就是可以访问正常的业务接口了)。

我们要完成以上操作,会涉及到web开发中的两个技术:

  1. 会话技术
  2. 统一拦截技术

而统一拦截技术现实方案也有两种:

  1. Servlet规范中的Filter过滤器
  2. Spring提供的interceptor拦截器

会话技术

会话技术介绍

什么是会话?

  • 在我们日常生活当中,会话指的就是谈话、交谈。
  • 在web开发当中,会话指的就是浏览器与服务器之间的一次连接,我们就称为一次会话。

 在用户打开浏览器第一次访问服务器的时候,这个会话就建立了,直到有任何一方断开连接,此时会话就结束了。在一次会话当中,是可以包含多次请求和响应的。比如:打开了浏览器来访问web服务器上的资源(浏览器不能关闭、服务器不能断开)

  • 第1次:访问的是登录的接口,完成登录操作
  • 第2次:访问的是部门管理接口,查询所有部门数据
  • 第3次:访问的是员工管理接口,查询员工数据

只要浏览器和服务器都没有关闭,以上3次请求都属于一次会话当中完成的。

需要注意的是:会话是和浏览器关联的,当有三个浏览器客户端和服务器建立了连接时,就会有三个会话。同一个浏览器在未关闭之前请求了多次服务器,这多次请求是属于同一个会话。比如:1、2、3这三个请求都是属于同一个会话。当我们关闭浏览器之后,这次会话就结束了。而如果我们是直接把web服务器关了,那么所有的会话就都结束了。

知道了会话的概念了,接下来我们再来了解下会话跟踪。
会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享数据。

服务器会接收很多的请求,但是服务器是需要识别出这些请求是不是同一个浏览器发出来的。比如:1和2这两个请求是不是同一个浏览器发出来的,3和5这两个请求不是同一个浏览器发出来的。如果是同一个浏览器发出来的,就说明是同一个会话。如果是不同的浏览器发出来的,就说明是不同的会话。而识别多次请求是否来自于同一浏览器的过程,我们就称为会话跟踪。

我们使用会话跟踪技术就是要完成在同一个会话中,多个请求之间进行共享数据。

为什么要共享数据呢?
由于HTTP是无状态协议,在后面请求中怎么拿到前一次请求生成的数据呢?此时就需要在一次会话的多次请求之间进行数据共享

会话跟踪技术有两种:
1. Cookie(客户端会话跟踪技术)

  • 数据存储在客户端浏览器当中

2. Session(服务端会话跟踪技术)

  • 数据存储在储在服务端

3. 令牌技术

会话跟踪方案

方案一Cookie

cookie 是客户端会话跟踪技术,它是存储在客户端浏览器的,我们使用 cookie 来跟踪会话,我们
就可以在浏览器第一次发起请求来请求服务器的时候,我们在服务器端来设置一个cookie。
比如第一次请求了登录接口,登录接口执行完成之后,我们就可以设置一个cookie,在 cookie 当中我们就可以来存储用户相关的一些数据信息。比如我可以在 cookie 当中来存储当前登录用户的用户名,用户的ID。
服务器端在给客户端在响应数据的时候,会自动的将 cookie 响应给浏览器,浏览器接收到响应回来的 cookie 之后,会自动的将 cookie 的值存储在浏览器本地。接下来在后续的每一次请求当中,
都会将浏览器本地所存储的 cookie 自动地携带到服务端。

接下来在服务端我们就可以获取到 cookie 的值。我们可以去判断一下这个 cookie 的值是否存
在,如果不存在这个cookie,就说明客户端之前是没有访问登录接口的;如果存在 cookie 的值,就说明客户端之前已经登录完成了。这样我们就可以基于 cookie 在同一次会话的不同请求之间来共享数据。

在介绍流程的时候,用了 3 个自动:

  • 服务器会 自动 的将 cookie 响应给浏览器。
  • 浏览器接收到响应回来的数据之后,会 自动 的将 cookie 存储在浏览器本地。
  • 在后续的请求当中,浏览器会 自动 的将 cookie 携带到服务器端。

为什么这一切都是自动化进行的?

是因为 cookie 它是 HTP 协议当中所支持的技术,而各大浏览器厂商都支持了这一标准。在 HTTP协议官方给我们提供了一个响应头和请求头

  • 响应头 Set-Cookie :设置Cookie数据的
  • 请求头 Cookie:携带Cookie数据的
     

@Slf4j
@RestController
public class SessionController {
    //设置Cookie
    @GetMapping("/c1")
    public Result cookie1(HttpServletResponse response){
        response.addCookie(new Cookie("login_username","itheima"));
        //设置Cookie/响应Cookie
        return Result.success();
     }
 
    //获取Cookie
    @GetMapping("/c2")
    public Result cookie2(HttpServletRequest request){
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            if(cookie.getName().equals("login_username")){
                System.out.println("login_username:
                "+cookie.getValue()); //输出name为login_username的cookie
             }
         }
        return Result.success();
     }
} 

访问c1接口,设置Cookie,http://localhost:8080/c1

我们可以看到,设置的cookie,通过响应头Set-Cookie响应给浏览器,并且浏览器会将Cookie,存
储在浏览器端。


 

访问c2接口 http://localhost:8080/c2,此时浏览器会自动的将Cookie携带到服务端,是
通过请求头Cookie,携带的。

 

优缺点:

优点:HTTP协议中支持的技术(像Set-Cookie 响应头的解析以及 Cookie 请求头数据的携
带,都是浏览器自动进行的,是无需我们手动操作的)

缺点:

  • 移动端APP(Android、IOS)中无法使用Cookie
  • 不安全,用户可以自己禁用Cookie
  • Cookie不能跨域

跨域介绍:

  • 现在的项目,大部分都是前后端分离的,前后端最终也会分开部署,前端部署在服务器192.168.150.200 上,端口 80,后端部署在 192.168.150.100上,端口 8080
  • 我们打开浏览器直接访问前端工程,访问url:http://192.168.150.200/login.html
  • 然后在该页面发起请求到服务端,而服务端所在地址不再是localhost,而是服务器的IP地址192.168.150.100,假设访问接口地址为:http://192.168.150.100:8080/login
  • 那此时就存在跨域操作了,因为我们是在 http://192.168.150.200/login.html 这个页面上访问了http://192.168.150.100:8080/login 接口
  • 此时如果服务器设置了一个Cookie,这个Cookie是不能使用的,因为Cookie无法跨域

区分跨域的维度:

  • 协议
  • IP/协议
  • 端口

只要上述的三个维度有任何一个维度不同,那就是跨域操作

方案二Session

Session,它是服务器端会话跟踪技术,所以它是存储在服务器端的。而Session 的底层其实就是基于我们刚才所介绍的 Cookie 来实现的。

获取Session

如果我们现在要基于 Session 来进行会话跟踪,浏览器在第一次请求服务器的时候,我们就可
以直接在服务器当中来获取到会话对象Session。如果是第一次请求Session ,会话对象是不存
在的,这个时候服务器会自动的创建一个会话对象Session 。而每一个会话对象Session ,它
都有一个ID(示意图中Session后面括号中的1,就表示ID),我们称之为 Session 的ID。

响应Cookie (JSESSIONID)

接下来,服务器端在给浏览器响应数据的时候,它会将 Session 的 ID 通过 Cookie 响应给浏览器。其实在响应头当中增加了一个 Set-Cookie 响应头。这个 Set-Cookie 响应头对应的值是不是cookie? cookie 的名字是固定的 JSESSIONID 代表的服务器端会话对象
Session 的 ID。浏览器会自动识别这个响应头,然后自动将Cookie存储在浏览器本地。

查找Session

 接下来,在后续的每一次请求当中,都会将 Cookie 的数据获取出来,并且携带到服务端。接下
来服务器拿到JSESSIONID这个 Cookie 的值,也就是 Session 的ID。拿到 ID 之后,就会从众多的 Session 当中来找到当前请求对应的会话对象Session。

这样我们是不是就可以通过 Session 会话对象在同一次会话的多次请求之间来共享数据了?
好,这就是基于 Session 进行会话跟踪的流程。

@Slf4j
@RestController
public class SessionController {
    @GetMapping("/s1")
    public Result session1(HttpSession session){
        log.info("HttpSession-s1: {}", session.hashCode());
        session.setAttribute("loginUser", "tom"); //往session中存储数
        据
        return Result.success();
     }
    @GetMapping("/s2")
    public Result session2(HttpServletRequest request){
        HttpSession session = request.getSession();
        log.info("HttpSession-s2: {}", session.hashCode());
        Object loginUser = session.getAttribute("loginUser"); //从
        session中获取数据
        log.info("loginUser: {}", loginUser);
        return Result.success(loginUser);
     }
}

 访问 s1 接口,http://localhost:8080/s1

请求完成之后,在响应头中,就会看到有一个Set-Cookie的响应头,里面响应回来了一个Cookie,就是JSESSIONID,这个就是服务端会话对象 Session 的ID。

访问 s2 接口,http://localhost:8080/s2

接下来,在后续的每次请求时,都会将Cookie的值,携带到服务端,那服务端呢,接收到Cookie之后,会自动的根据JSESSIONID的值,找到对应的会话对象Session。
那经过这两步测试,大家也会看到,在控制台中输出如下日志:

两次请求,获取到的Session会话对象的hashcode是一样的,就说明是同一个会话对象。而且,第一次请求时,往Session会话对象中存储的值,第二次请求时,也获取到了。 那这样,我们就可以通过Session会话对象,在同一个会话的多次请求之间来进行数据共享了。
优缺点:

优点:Session是存储在服务端的,安全

缺点:

  • 服务器集群环境下无法直接使用Session
  • 移动端APP(Android、IOS)中无法使用Cookie
  • 用户可以自己禁用Cookie
  • Cookie不能跨域

PS:Session 底层是基于Cookie实现的会话跟踪,如果Cookie不可用,则该方案,也就失效
了。

服务器集群环境为何无法使用Session?

首先第一点,我们现在所开发的项目,一般都不会只部署在一台服务器上,因为一台服务器
会存在一个很大的问题,就是单点故障。所谓单点故障,指的就是一旦这台服务器挂了,整
个应用都没法访问了。

所以在现在的企业项目开发当中,最终部署的时候都是以集群的形式来进行部署,也就是同
一个项目它会部署多份。比如这个项目我们现在就部署了 3 份。
而用户在访问的时候,到底访问这三台其中的哪一台?其实用户在访问的时候,他会访问一
台前置的服务器,我们叫负载均衡服务器,它的作用就是将前端发起的请求均匀的分发给后面的这三台服务器。

此时假如我们通过 session 来进行会话跟踪,可能就会存在这样一个问题。用户打开浏览
器要进行登录操作,此时会发起登录请求。登录请求到达负载均衡服务器,将这个请求转给
了第一台 Tomcat 服务器。
Tomcat 服务器接收到请求之后,要获取到会话对象session。获取到会话对象 session
之后,要给浏览器响应数据,最终在给浏览器响应数据的时候,就会携带这么一个 cookie
的名字,就是 JSESSIONID ,下一次再请求的时候,是不是又会将 Cookie 携带到服务
端?
好。此时假如又执行了一次查询操作,要查询部门的数据。这次请求到达负载均衡服务器之
后,负载均衡服务器将这次请求转给了第二台 Tomcat 服务器,此时他就要到第二台
Tomcat 服务器当中。根据JSESSIONID 也就是对应的 session 的 ID 值,要找对应
的 session 会话对象。
我想请问在第二台服务器当中有没有这个ID的会话对象 Session, 是没有的。此时是不
是就出现问题了?我同一个浏览器发起了 2 次请求,结果获取到的不是同一个会话对象,
这就是Session这种会话跟踪方案它的缺点,在服务器集群环境下无法直接使用Session。

上面这两种传统的会话技术,在现在的企业开发当中是不是会存在很多的问题。 为了解决
这些问题,在现在的企业开发当中,基本上都会采用第三种方案,通过令牌技术来进行会话跟踪。接下来我们就来介绍一下令牌技术,来看一下令牌技术又是如何跟踪会话的。

方案三 令牌技术

 所提到的令牌,其实它就是一个用户身份的标识,看似很高大上,很神秘,其实本质就是一个
字符串。

如果通过令牌技术来跟踪会话,我们就可以在浏览器发起请求。在请求登录接口的时候,如果登录成功,我就可以生成一个令牌,令牌就是用户的合法身份凭证。接下来我在响应数据的时候,我就可以直接将令牌响应给前端。
接下来我们在前端程序当中接收到令牌之后,就需要将这个令牌存储起来。这个存储可以存储在
cookie 当中,也可以存储在其他的存储空间(比如:localStorage)当中。
接下来,在后续的每一次请求当中,都需要将令牌携带到服务端。携带到服务端之后,接下来我们就需要来校验令牌的有效性。如果令牌是有效的,就说明用户已经执行了登录操作,如果令牌是无效的,就说明用户之前并未执行登录操作。
此时,如果是在同一次会话的多次请求之间,我们想共享数据,我们就可以将共享的数据存储在令牌当中就可以了。

优点:

  • 支持PC端、移动端
  • 解决集群环境下的认证问题
  • 减轻服务器的存储压力(无需在服务器端存储)

缺点:需要自己实现(包括令牌的生成、令牌的传递、令牌的校验)
 


总结

通过本篇博客的深入分析,我们全面探讨了登录校验、会话技术与会话跟踪技术的实现与应用。在Web开发中,登录校验是确保用户身份的第一道防线,而会话管理则确保了用户在多次请求中保持一致性和连续性。我们详细介绍了常见的会话跟踪方式,包括Cookies、Session、Jwt,并分析了它们各自的优缺点,帮助开发者做出更合适的技术选型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/911543.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ffmpeg:视频字幕嵌入(GPU加速)

实现方案 参考指令 ffmpeg -i input_video.mp4 -vf "subtitlessubtitles.srt" output_video.mp4 解决因文件名称复杂导致的指令执行失败问题(引号给文件框起来) ffmpeg -i "A.mp4" -vf "subtitlesB.srt" "c.mp4&qu…

qt QListWidget详解

1、概述 QListWidget 是 Qt 框架中的一个类,它提供了一个基于模型的视图,用于显示项目的列表。QListWidget 继承自 QAbstractItemView 并为项目列表提供了一个直观的接口。与 QTreeView 和 QTableView 不同,QListWidget 是专门为单行或多行项…

UE5 材质篇 0 创建一个材质

首先在starter里的shape里拖入一个几何到场景里 我选了个sphere 然后开始制作一个材质,直接右键点击 进入材质的蓝图界面 先来个纹理采样 左侧detail里选个图给他 type这里可以指定他是其他图片,例如normal map 采样一个之前给UV加个动态offset

AOSP沙盒android 11

这里介绍一下aosp装系统 什么是aosp AOSP(Android Open Source Project)是Android操作系统的开源版本。 它由Google主导,提供了Android的源代码和相关工具,供开发者使用和修改。 AOSP包含了Android的核心组件和API,使…

Linux挖矿病毒(kswapd0进程使cpu爆满)

一、摘要 事情起因:有台测试服务器很久没用了,突然监控到CPU飙到了95以上,并且阿里云服务器厂商还发送了通知消息,【阿里云】尊敬的xxh: 经检测您的阿里云服务(ECS实例)i-xxx存在挖矿活动。因此很明确服务器中挖矿病毒…

flink 内存配置(二):设置TaskManager内存

flink 内存配置(一):设置Flink进程内存 flink 内存配置(二):设置TaskManager内存 flink 内存配置(三):设置JobManager内存 flink 内存配置(四)…

基于YOLO11/v10/v8/v5深度学习的建筑墙面损伤检测系统设计与实现【python源码+Pyqt5界面+数据集+训练代码】

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

sheng的学习笔记-tidb框架原理

目录 TiDB整体架构 TiDB架构图 组件-TiDB Server 架构图 流程 关系型数据转成kv ​编辑 组件-TiKV Server​ 架构图 主要功能: 列簇 组件-列存储TiFlash 组件-分布式协调层:PD PD架构图 路由 Region Cache back off TSO分配 概念 解…

HarmonyOS-消息推送

一. 服务简述 Push Kit(推送服务)是华为提供的消息推送平台,建立了从云端到终端的消息推送通道。所有HarmonyOS 应用可通过集成 Push Kit,实现向应用实时推送消息,使消息易见,构筑良好的用户关系&#xff0…

linux 安装anaconda3

1.下载 使用repo镜像网址下载对应安装包 右击获取下载地址,使用终端下载 wget https://repo.anaconda.com/archive/Anaconda3-2024.02-1-Linux-x86_64.sh2.安装 使用以下命令可直接指定位置 bash Anaconda3-2024.02-1-Linux-x86_64.sh -b -p /home/anaconda3也…

如何学习C++游戏开发

学习C游戏开发是一个涉及多个领域的复杂过程,包括编程、游戏设计、图形学等。 1. **学习C基础**: - 掌握C的基本语法和面向对象编程。 - 学习C标准库,特别是STL(标准模板库)。 2. **理解游戏开发概念**&#xf…

tinymce扩展功能:1、行高、段落间距、格式刷;2、视频上传进度条;3、对复制的图片设置尺寸

tinymce扩展功能:1、行高、段落间距、格式刷;2、视频上传进度条;3、对复制的图片设置尺寸 一、需求描述二、行高、段落间距、格式刷插件三、实现视频上传的进度条、对复制的图片设置尺寸 一、需求描述 使用技术: vue2 tinymce5.…

C++【string类,模拟实现string类】

🌟个人主页:落叶 🌟当前专栏: C专栏 目录 为什么学习string类 C语言中的字符串 标准库中的string类 auto和范围for auto关键字 迭代器 范围for string类的常用接口说明和使用 1. string类对象的常见构造 2.string类对象的容量操作 3…

内网部署web项目,外网访问不了?只有局域网能访问!怎样解决?

相关技术 要实现“内网部署,外网访问”,可以使用内网穿透、VPN技术、DMZ主机、端口映射等方法。以下是对这些方法的详细解释: 一、内网穿透 内网穿透是一种技术,它通过将内网设备映射到公网上的方式,实现外网访问内…

鸿蒙ArkTS中的布局容器组件(Scroll、List、Tabs)

1、Scroll组件 Scroll组件是一个可滚动的容器组件,用于在子组件的布局尺寸超过父组件尺寸时提供滚动功能。它允许在其内部容纳超过自身显示区域的内容,并通过滚动机制来查看全部内容。这对于显示大量信息(如长列表、长篇文本或大型图像等&…

apache-seata-2.1.0 AT模式使用篇(配置简单)

最近在研究seata的AT模式,先在本地搭建了一个演示demo,看看seata是如何使用的。在网上搜的demo,配置相对来说都比较多。我最终搭建的版本,配置较少,所以写篇文章分享下,希望能帮到对seata感兴趣的小伙伴。先…

卖家必看:亚马逊、temu自养号测评拍单过程中的关键技巧分享

自养号测评是一个循序渐进的过程,许多卖家在测评后却发现流量排名并未显著提升,甚至遭遇了平台警告。即便采用了相同的测评技术,结果却大相径庭。究其原因,除了技术层面的差异,更在于对平台风控规则、测评技巧及细致执…

单细胞 RNA 测序分析的当前最佳实践:教程-文献精读80

Current best practices in single‐cell RNA‐seq analysis: a tutorial 单细胞 RNA 测序分析的当前最佳实践:教程 摘要 单细胞 RNA 测序使基因表达的研究达到了前所未有的分辨率。这项技术的前景吸引了越来越多的用户使用单细胞分析方法。随着更多分析工具的出现…

微积分复习笔记 Calculus Volume 1 - 4.8 L’Hôpital’s Rule

4.8 L’Hpital’s Rule - Calculus Volume 1 | OpenStax

【大语言模型】ACL2024论文-07 BitDistiller: 释放亚4比特大型语言模型的潜力通过自蒸馏

【大语言模型】ACL2024论文-07 BitDistiller: 释放亚4比特大型语言模型的潜力通过自蒸馏 目录 文章目录 【大语言模型】ACL2024论文-07 BitDistiller: 释放亚4比特大型语言模型的潜力通过自蒸馏目录摘要研究背景问题与挑战如何解决创新点算法模型实验效果代码推荐阅读指数&…