Security OAuth2 SSO单点登录(一)

文章目录

  • 学习链接
  • 单点登录
    • cookie+session&token模式&前端无感token刷新&双token模式&黑名单
    • auth-server
      • 引入依赖
      • application.yml
      • AuthServerConfig
      • SecurityConfig
      • UserController
      • login.html
    • client1
      • 引入依赖
      • application.yml配置文件
      • SecurityConfig
      • Client1Application
      • HaloController
      • index.html
    • client2
      • 引入依赖
      • application.yml配置文件
      • SecurityConfig
      • Client2Application
      • HaloController
      • index.html

学习链接

cookie & session & localStorage & sessionStorage - 自己的

session共享原理 - 自己的

spring-session学习 - 自己的

OAuth2流程和源码解析 - 自己的 - 有道笔记

Security OAuth2 授权 & JWT - 自己的

Spring Security整合Gitee第三方登录 - 自己的

JWT使用 - 自己的

token无感刷新【渡一教育】

单点登录的模式【渡一教育】

Spring Boot+OAuth2,一个注解搞定单点登录!

SpringCloud微服务实战——搭建企业级开发框架(四十):使用Spring Security OAuth2实现单点登录(SSO)系统

Spring Security Oauth2 SSO单点登录配置及原理深度剖析

多系统单点登录(sso)设计

Java-前后端分离-单点登录(SSO二级跨域和跨一级域名)

【学习笔记】:基于SpringBoot实现单点登录sso测试demo

springsecurity实现单点登录

主要是体会下,security是如何考虑单点登录的,以及它的具体做法:全部代码 - gitee

单点登录

cookie+session&token模式&前端无感token刷新&双token模式&黑名单

当1个公司开发了多个系统时,如系统A,系统B,系统C。用户在登录A系统时,需要跳转到B系统时,在B系统又要去登录一遍,这无疑时是比较麻烦的。

这时候,就可以抽离出1个统一认证中心服务专门处理用户认证。首先,当用户访问系统A时,由于用户没有登录,所以会跳转到统一认证中心登录,当用户登录成功后,在统一认证中心下可以使用cookie + session的机制保存用户的登录信息,然后用户跳转到系统A,并且携带登录统一认证中心成功的凭证(等等,这里面可能会涉及到cookie的不可跨域名性,就算存在localStorage里面也是有着隔离,这些是具体的细节,暂不考虑,实现时再说),这样系统A就收到了用户发过来的凭证,然而系统A却不能鉴定该凭证的真实性以及该凭证所代表的用户信息,因此系统A需要发送请求给认证中心获取该凭证所对应的用户数据(等等,如果认证服务与系统A在浏览器都会携带同1个cookie时,是可以用spring-session实现会话共享的,也就不用发请求了。补充:访问这2个服务能不能携带同1个cookie是有条件的)。系统A通过发请求给认证中心校验凭证有效时,就会在凭证允许的权限范围内给用户访问。此时,当用户访问系统B时,要仍然携带凭证(等等,此时跳转到系统B,这个凭证由于不可跨域名性,不一定能带上,可以先跳回认证中心,因为已经在认证中心登录过,再跳转到系统B,并携带凭证),系统B也同样需要发请求给认证中心,校验凭证的真实性和用户信息,如果没有问题,则允许用户访问。

上面实现的大致逻辑就是这样,里面存在1个问题:如果某个系统,比如系统C比较热门,用户比较多的情况下,比如:200万用户都活跃,这样认证中心就得统一管理这么多已登录用户的信息,并且每一次用户访问系统C都需要访问认证中心来获取用户信息。那么对于认证中心来说,1个是存储用户信息问题(这个可以用redis解决),1个是处理大量校验凭证请求的问题,这样就很有可能导致认证中心不堪重负,假设此时认证中心挂了,那么所有的子系统就全都报废了(这个就比较严重了,各个子系统都依赖这个认证中心才能正常工作)。但是,这样集中式的管理用户会话数据,会比较方便对用户进行控制,比如让用户下线只需要删除这个会话即可,那么用户会立即需要重新认证登录。

对于上面的问题,使用jwt令牌可以解决,当用户在统一认证中心登录成功时,生成1个jwt令牌,这个jwt令牌由3部分组成:1个令牌类型和算法,1个令牌内容可base64解码,1个签名可验签。用户登录成功后,保存此令牌。然后,拿着这个令牌去访问系统A,因为jwt令牌上已经携带的内容包含了用户信息,所以系统A可以直接读取这个jwt令牌中的用户信息,并且可以验证签名来判断jwt令牌的内容是否被篡改过,如果没有被篡改过,并且这个jwt令牌的失效时间还长,并没有过期。那么系统A就直接给用户返回内容即可。此时,用户访问系统C也是一样携带这个令牌。(至于跳转系统C的时候,是怎么携带这个令牌,具体实现的时候再说,反正就是这么个意思)

上面使用jwt的token方式就是这样,认证中心不再保存已登录用户的信息,而是给了登录用户1个可识别和可验签的代表用户信息的令牌。认证中心也不再处理校验凭证的请求了。即便认证中心挂掉了,此令牌仍然可在各子系统中使用。这样也会带来一些问题:不能对用户进行方便控制,不好做到让用户立即下线。令牌一旦颁发出去,那么想撤销这个令牌就相对来说没那么容易了。虽然,也可以采用黑名单的方式,每个子系统在redis中维护着自己黑名单(各个子系统不一定使用的是同一个redis),但撤销还得通知到其它系统。

jwt令牌减轻了认证中心的压力,但带来了撤销令牌的麻烦。因此,OAuth2中就涉及到了1个刷新令牌的机制。既然令牌不能立即撤销,那么给这个令牌1个比较短的过期时间,比如:2个小时。也就是,用户登录后,会获得2个令牌,1个访问令牌,1个刷新令牌。用户使用访问令牌访问各个子系统,但因为访问令牌是有时间限制的,一旦到了过期时间,访问令牌就被各个子系统识别出来已经过期了,无法使用。此时,再让用户登录一遍的话,就也显得麻烦了,因此就让用户需要拿着刷新令牌(这个刷新令牌的有效时间比访问令牌的时间要长,比如:7天或1个月,)去认证中心换取新的访问令牌,然后拿着这个新的访问令牌去访问各个子系统。这样,用户每隔一段比较短的时间,就得拿着刷新令牌获取访问令牌。如果此时要控制用户的话,等到用户下一次获取访问令牌时,不给他刷新就行了,那么用户就只得重新登录了,只是没有那么即时了。

如果需要即时性,那么就由认证服务给各子系统通知一下(这个通知接口也得做权限控制),更新各子系统存在redis中的黑名单,黑名单记录用户的id(因为令牌颁发后,不会记录该令牌具体的值,否则跟在会话中记录用户用户数据没啥区别了,同时也是内存负担)存储个2小时,那么这2个小时内,用户使用旧的访问令牌是无法访问的,当用户使用刷新令牌获取新的访问令牌时,这时候就可以决定是否颁发新的令牌,如果颁发新的访问令牌,则通知各个子系统从黑名单中主动移除。

还有1个比较严重的问题需要考虑下,如果黑名单只是记录用户的id的话,可能还是不够。假设用户登录了1次之后,获取了访问令牌和刷新令牌,持有访问令牌在令牌有效期内可以任意访问用户资源,持有刷新令牌同样在有效期内可重新获取刷新令牌。那么如果用户修改了密码的情况下,它们在有效期内仍然能够使用,令牌的重要性甚至上升到了与用户密码凭据同样的高度。同样,用户在多个设备而登录多次时,那么就会存在1个用户有多个访问令牌和多个刷新令牌的存在。因此,登录成功后,最好是将用户id和对应的访问令牌和刷新令牌的JTI属性(令牌唯一标识)关系也给保存下来。当用户修改密码时,找到所有之前的访问令牌id,把它们通知给各个子系统,让它们写到黑名单中,找到所有之前的刷新令牌id,然后把他们写到认证服务中心的黑名单中,并且也可以做到最多允许同时在线客户端数量,根据设置确定踢人模式。而一旦用户修改密码,则将之前颁发给该用户的所有访问令牌的JTI标识写到所有子系统,同时,把用户对应的刷新令牌写到认证中心黑名单。

auth-server

引入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.6.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>org.javaboy</groupId><artifactId>auth-server</artifactId><version>0.0.1-SNAPSHOT</version><name>auth-server</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version><spring-cloud.version>Hoxton.SR3</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-security</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

application.yml

server:port: 1110

AuthServerConfig

@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {@AutowiredPasswordEncoder passwordEncoder;@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security.checkTokenAccess("permitAll()");}@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient("c1").secret(passwordEncoder.encode("secret")).autoApprove(true).redirectUris("http://localhost:1111/login", "http://localhost:1112/login").scopes("user").accessTokenValiditySeconds(7200).authorizedGrantTypes("authorization_code");}
}

SecurityConfig

@Configuration
@Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {@BeanPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Overridepublic void configure(WebSecurity web) throws Exception {web.ignoring().antMatchers("/login.html", "/css/**", "/js/**", "/images/**", "/favicon.ico");}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.requestMatchers().antMatchers("/login").antMatchers("/oauth/authorize").and().authorizeRequests().anyRequest().authenticated().and().formLogin().loginPage("/login.html").loginProcessingUrl("/login").permitAll().and().csrf().disable();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("zzhua").password(passwordEncoder().encode("zzhua")).roles("admin");}
}

UserController

@RestController
public class UserController {@GetMapping("/user")public Principal getCurrentUser(Principal principal) {return principal;}
}

login.html

<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document</title>
</head>
<body>
<div style="overflow: hidden"><div class="login-form"><h1>统一认证平台</h1><form action="/login" method="post"><div class="login-item"><span class="login-item-name">用户名: </span><input type="text" name="username"/></div><div class="login-item"><span class="login-item-name">密码: </span><input type="text" name="password"/></div><div class="login-item submit"><input type="submit" value="登录"/></div></form></div>
</div>
</body>
<style>* {box-sizing: border-box;}body {overflow: hidden;margin: 0;}h1 {margin-left: 25px;}.login-form {width: 600px;margin: 120px auto;text-align: center;border: 1px solid #eee;border-radius: 5px;box-shadow: 2px 9px 6px 0px #ddd;}.login-form form {width: 60%;margin: 20px auto;padding: 10px 0 50px;}.login-item {display: flex;margin-bottom: 20px;height: 26px;line-height: 32px;}.login-item .login-item-name {width: 100px;text-align: right;padding-right: 15px;}.login-item input {flex: 1;outline: none;border: 1px solid #ddd;height: 32px;font-size: 18px;font-weight: lighter;padding-left: 10px;border-radius: 5px;}.login-item.submit {padding-left: 100px;}.login-item.submit input[type=submit]{border: none;background-color: #86bdcf;letter-spacing: 10px;color: #ffffff;transition: all .2s;}.login-item.submit input[type=submit]:hover {background-color: #6da0b2;}</style>
</html>

client1

引入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.6.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>org.javaboy</groupId><artifactId>client1</artifactId><version>0.0.1-SNAPSHOT</version><name>client1</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version><spring-cloud.version>Hoxton.SR3</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-security</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

application.yml配置文件

server:port: 1111servlet:session:cookie:name: s1
security:oauth2:client:client-id: c1client-secret: secretuser-authorization-uri: http://localhost:1110/oauth/authorizeaccess-token-uri: http://localhost:1110/oauth/tokenresource:user-info-uri: http://localhost:1110/user

SecurityConfig

@Configuration
@EnableOAuth2Sso
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().csrf().disable();}
}

Client1Application

@SpringBootApplication
public class Client1Application {public static void main(String[] args) {SpringApplication.run(Client1Application.class, args);}}

HaloController

@RestController
public class HaloController {@GetMapping("/halo")public String halo() {Authentication authentication = SecurityContextHolder.getContext().getAuthentication();System.out.println(authentication.getName() + Arrays.toString(authentication.getAuthorities().toArray()));return "halo-1111";}
}

index.html

<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document</title>
</head>
<body><h1>【client1】</h1><a href="http://localhost:1112">跳转到client2</a><button id="btn1">获取client1中的数据</button><button id="btn2">获取client2中的数据</button></body>
<script>let btn1 = document.querySelector("#btn1")let btn2 = document.querySelector("#btn2")btn1.addEventListener('click', function () {fetch("http://localhost:1111/halo")})btn2.addEventListener('click', function () {fetch("http://localhost:1112/halo")})
</script>
</html>

client2

引入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.6.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>org.javaboy</groupId><artifactId>client2</artifactId><version>0.0.1-SNAPSHOT</version><name>client2</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version><spring-cloud.version>Hoxton.SR3</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-security</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

application.yml配置文件

server:port: 1112servlet:session:cookie:name: s2
security:oauth2:client:client-id: c1client-secret: secretuser-authorization-uri: http://localhost:1110/oauth/authorizeaccess-token-uri: http://localhost:1110/oauth/tokenresource:user-info-uri: http://localhost:1110/user

SecurityConfig

@Configuration
@EnableOAuth2Sso
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().csrf().disable();}
}

Client2Application

@SpringBootApplication
public class Client2Application {public static void main(String[] args) {SpringApplication.run(Client2Application.class, args);}}

HaloController

@RestController
public class HaloController {@CrossOrigin@GetMapping("/halo")public String halo() {Authentication authentication = SecurityContextHolder.getContext().getAuthentication();System.out.println(authentication.getName() + Arrays.toString(authentication.getAuthorities().toArray()));return "halo";}
}

index.html

<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document</title>
</head>
<body><h1>【client2】</h1><a href="http://localhost:1111">跳转到client1</a><button id="btn1">获取client1中的数据</button><button id="btn2">获取client2中的数据</button></body>
<script>let btn1 = document.querySelector("#btn1")let btn2 = document.querySelector("#btn2")btn1.addEventListener('click', function () {fetch("http://localhost:1111/halo")})btn2.addEventListener('click', function () {fetch("http://localhost:1112/halo")})
</script>
</html>

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中央事件bus

中央事件bus的使用 使用场景&#xff1a;当需要传递给多个组件的时候例如父组件->子组件->孙组件&#xff0c;甚至还得传递到更深的组件的时候中央事件就起到了作用&#xff0c;不需要一直传递。bus其实就是一个发布订阅模式&#xff0c;利用vue的自定义事件机制 // 事…

探索减轻 AI 说服伤害的机制方法

随着生成式人工智能&#xff08;AI&#xff09;系统在各个领域的广泛应用&#xff0c;其说服能力也日益增强&#xff0c;引发了对 AI 说服可能带来伤害的担忧。AI 说服的伤害不仅来源于说服的结果&#xff0c;还包括说服过程中可能对个体或社会造成的不利影响。为了系统性地研究…

学习Uni-app开发小程序Day27

这一章学习了几个功能点&#xff0c;例如&#xff1a;try{}catch处理同步请求下载记录异常处理、onShareAppMessage分享好友和分享微信朋友圈、对分享页面传参进行特殊处理、共用分类列表页面实现我的下载和评分页面、使用mp-html富文本插件渲染公告详情页面 try{}catch处理同…

AI+低代码,打通企业大模型应用最后一公里!

一、AI的趋势与发展 一夜之间&#xff0c;微软的AI全宇宙似乎已成型。 5月22日凌晨&#xff0c;在一年一度的2024微软Build大会上&#xff0c;微软CEO萨蒂亚纳德拉一口气宣布了50多项AI能力更新&#xff0c;涵盖GPT-4o上云、自研Cobalt芯片、团队版Copilot、SOTA小模型等。 此…

网络通信过程的技术分析

网络通信过程的技术分析 目录 网络通信过程的技术分析 一、引言 二、网络通信基础 三、通信协议 四、数据传输过程 五、网络设备与通信 六、网络安全与通信 七、高级网络通信概念 八、结论 一、引言 网络通信是现代计算机网络中的核心活动&#xff0c;它涉及多个层面的…

Diffusion相关原理

Diffusion相关原理 1、数学&#xff1a;重参数化 &#xff08;用于高斯拟合求导&#xff09;变分推断原理 &#xff08;用于损失&#xff09; 2、生成模型系列1、AE自动编码器&#xff08;AutoEncoder&#xff09;2.VAE的模型架构模型原理数学原理AE和VAE对比 3、DDMP图像高斯加…

信息化项目必须进行验收测试吗?软件测试公司验收测试流程分享

信息化项目验收是指在软件开发完成之后&#xff0c;对其进行独立检查和确认&#xff0c;以确定它是否达到了预期的质量和功能需求。在进行验收之前&#xff0c;必须进行验收测试&#xff0c;这是非常重要的一步。 为什么要进行验收测试呢&#xff1f;好处可不少哦&#xff01;…

Flutter 中的 ExpansionTile 小部件:全面指南

Flutter 中的 ExpansionTile 小部件&#xff1a;全面指南 在 Flutter 应用中&#xff0c;ExpansionTile 是一个常用的折叠列表项&#xff0c;它允许用户点击标题来展开或折叠更多的内容。这个组件在实现可折叠列表、FAQ 部分或显示详情信息时非常有用。本文将详细介绍 Expansi…

张量视图(Tensor Views)

文章目录 前言1.torch.as_strided()2.torch.detach()3.torch.diagonal()4.torch.expand()5.torch.movedim()6.torch.narrow()7.torch.permute()8.torch.select()9.torch.squeeze()10.torch.transpose()11.torch.t()12.torch.real和torch.imag13.torch.unflatten()14.torch.unsq…

Redis教程(二十):Redis中Lua脚本的使用

Lua脚本 Lua 脚本主要在于提供一种强大且灵活的方式来扩展和定制应用程序的功能。在不同的场景和平台上,Lua 脚本的作用各不相同,以下是一些主要的用途: 嵌入式脚本 Lua 最初设计的目的就是作为一个嵌入到应用程序中的脚本语言。这使得应用开发者可以提供一种途径,让最…

Flutter 中的 LinearProgressIndicator 小部件:全面指南

Flutter 中的 LinearProgressIndicator 小部件&#xff1a;全面指南 在用户界面设计中&#xff0c;进度指示器是提供用户等待反馈的重要元素。Flutter 提供了多种进度指示器组件&#xff0c;其中 LinearProgressIndicator 用于展示水平的进度条。本文将详细介绍 LinearProgres…

【React】二次封装Antd的Table组件

使用Table并不难&#xff0c;但是每次使用都会伴随着很大一部分逻辑&#xff0c;如loding效果、表格分页筛选排序、调接口完毕后赋值等等&#xff0c;使用方法基本一致&#xff0c;所以可以将他们二次封装&#xff0c;从而减少代码量&#xff0c;提升代码可读性。 二次封装表格…

5.29高通技术分享抢先看 | 2024高通边缘智能创新应用大赛公开课

火力全开&#xff01;2024高通边缘智能创新应用大赛首期公开课将在5月29日晚上8点炫酷启动&#xff01; 届时&#xff0c;来自大赛主办方高通技术公司的产品市场总监李骏捷和高级资深工程师李万俊将于云端聚首&#xff0c;带来一场关于边缘智能的前沿技术对话。 各位参赛者及…

预防侵权知识丨什么是图形商标?怎么用产品图片进行图形商标查询检索?

图形商标查询检索是跨境电商预防侵权中重要的一环&#xff0c;但是有很多卖家对图形商标不太了解&#xff0c;也不知道怎么进行图形商标的查询检索。所以&#xff0c;我们一起来看下。 一、什么是图形商标 图形商标是商标的一种&#xff0c;指的是由几何图形或其它事物图案构…

网络流量监控指标有哪些?

目录 什么是网络流量监控&#xff1f; 关键网络流量监控指标 带宽利用率 网络延迟&#xff08;Latency&#xff09; 抖动&#xff08;Jitter&#xff09; 丢包率&#xff08;Packet Loss Rate&#xff09; 吞吐量&#xff08;Throughput&#xff09; 会话数量&#xff0…

深入理解C++智能指针系列(三)

引言 在现代软件开发中&#xff0c;内存管理是一个核心主题&#xff0c;特别是在使用C这类需要手动管理内存的语言时。智能指针作为一种高效的工具&#xff0c;能够简化内存管理的复杂性。本文将讨论如何利用 std::unique_ptr 来封装复杂的内存管理任务&#xff0c;特别是在涉…

30秒学会一个ChatGpt-4o小技巧 --- 照片漫画化

文章目录 选择照片修改图片 选择照片 先选择自己的一张照片 当然首先你得能够访问ChatGpt-4o, 图片生成能力只有ChatGpt-4才有 所以我们先登录到 国内能够使用的ChatGpt网站: 我要超级GPT 然后把图片上传&#xff0c;再写提示词&#xff1a;请帮我把这种照片按照日系动漫风…

vue根据登录存储的性别来改变背景图

根据登录成功之后&#xff0c;并把信息存入到本地&#xff0c;在个人页面中&#xff0c;并取出来&#xff0c;并渲染它&#xff0c;这是一个根据存储的性别来渲染个人页面的背景图&#xff0c;男女性别不同&#xff0c;背景图也不一样。 template: <div class"top"…

IT 行业的现状剖析与未来展望:商业与技术的交织

今日&#xff0c;我无意间看到 CSDN 的创作话题&#xff1a;“我眼中的 IT 行业现状与未来趋势”&#xff0c;这引发了我对 IT 行业的深入思考。以下是我的一些个人见解&#xff0c;希望能得到大家的指正和交流&#xff0c;共同进步。 IT 行业的现状与未来趋势&#xff0c;这个…

云服务器有啥用?如何拥有一台自己的云服务器?

你们平时都把珍贵的学习资料藏在哪里&#xff1f; 你们是否也遇到过学习资料丢失&#xff0c;或者放在网盘被人发现的问题&#xff1f; 云服务器作为一种灵活、高效、可扩展的计算资源&#xff0c;为用户提供了强大的计算能力和存储空间。所以我们可以尝试通过云服务器来搭建…