常用中间件-OAuth2

news2024/11/26 14:42:11

1. 微服务权限校验Session共享

1.1 微服务权限校验

在这里插入图片描述
在这里插入图片描述
实现2号方案。使用Redis作为Session统一存储。

首先配置一下Nacos,参考https://blog.csdn.net/weixin_43917045/article/details/132852850

然后为每个服务添加验证机制,先导入依赖
在这里插入图片描述

        <!--  SpringSession Redis支持  -->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>
        <!--  添加Redis的Starter  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
		<!--使用SpringSecurity框架作为权限校验框架:-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

三个服务都需要添加以上依赖。

然后给三个服务都修改配置文件。
在这里插入图片描述
这样,默认情况下每个服务的接口都会被SpringSecurity所保护,只有登录成功后,才可以被访问。
启动nacos和三个服务。
此时访问borrow借阅接口http://localhost:8201/borrow/1会自动跳转到登陆接口http://localhost:8201/login
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
点击登录后进入redis-cli可以看到用户密码已存在。
在这里插入图片描述
此时访问book服务,可以看到直接能调用,不用登录,因为上次登录在borrow服务访问中已经存入账户密码信息。
在这里插入图片描述
此时先退出登录。
在这里插入图片描述
退出账户后访问http://localhost:8301/book/1就会跳转到登录页面http://localhost:8301/book/1
然后再进行登录,进行借阅接口访问,发现出错,是由于borrow服务调用user和book服务是远程调用形式,,而这种形式没有进行任何验证。出现这种情况原因是RestTemplate远程调用的时候,由于请求没有携带Session的Cookies,所以导致验证失败,访问不成功,返回401。因此存在不便。
在这里插入图片描述

2. OAuth 2.0实现单点登录

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.1 搭建验证服务器

还原不带任何spring cloud alibaba依赖的项目,
在这里插入图片描述
加入spring cloud依赖
在这里插入图片描述
创建auth-service(左上角新增moudle)并导入依赖。(图片中服务名称a打成o了)
在这里插入图片描述
在这里插入图片描述
编写配置类
在这里插入图片描述

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .anyRequest().authenticated()  //
                .and()
                .formLogin().permitAll();    //使用表单登录
    }
  
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        auth
                .inMemoryAuthentication()   //直接创建一个用户,懒得搞数据库了
                .passwordEncoder(encoder)
                .withUser("test").password(encoder.encode("123456")).roles("USER");
    }
  
  	@Bean   //这里需要将AuthenticationManager注册为Bean,在OAuth配置中使用
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}
@EnableAuthorizationServer   //开启验证服务器
@Configuration
public class OAuth2Configuration extends AuthorizationServerConfigurerAdapter {

    @Resource
    private AuthenticationManager manager;

    private final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

    /**
     * 这个方法是对客户端进行配置,一个验证服务器可以预设很多个客户端,
     * 之后这些指定的客户端就可以按照下面指定的方式进行验证
     * @param clients 客户端配置工具
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients
                .inMemory()   //这里我们直接硬编码创建,当然也可以像Security那样自定义或是使用JDBC从数据库读取
                .withClient("web")   //客户端名称,随便起就行
                .secret(encoder.encode("654321"))      //只与客户端分享的secret,随便写,但是注意要加密
                .autoApprove(false)    //自动审批,这里关闭,要的就是一会体验那种感觉
                .scopes("book", "user", "borrow")     //授权范围,这里我们使用全部all
                .authorizedGrantTypes("client_credentials", "password", "implicit", "authorization_code", "refresh_token");
                //授权模式,一共支持5种,除了之前我们介绍的四种之外,还有一个刷新Token的模式
                //这里我们直接把五种都写上,方便一会实验,当然各位也可以单独只写一种一个一个进行测试
                //现在我们指定的客户端就支持这五种类型的授权方式了
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) {
        security
                .passwordEncoder(encoder)    //编码器设定为BCryptPasswordEncoder
                .allowFormAuthenticationForClients()  //允许客户端使用表单验证,一会我们POST请求中会携带表单信息
                .checkTokenAccess("permitAll()");     //允许所有的Token查询请求
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints
                .authenticationManager(manager);
        //由于SpringSecurity新版本的一些底层改动,这里需要配置一下authenticationManager,才能正常使用password模式
    }
}

然后启动auth-service。
在这里插入图片描述
使用postman进行接口测试。

2.1.1客户端模式测试,

客户端模式只需要提供id和secret即可直接拿到token,但还需要添加一个grant_type表面我们的授权方式,默认请求路径为http://localhost:8500/sso/oauth/token
在这里插入图片描述
通过访问http://localhost:8500/sso/oauth/check_token来验证token是否有效
在这里插入图片描述

2.1.2 密码模式测试

密码模式还需要提供具体的用户名和密码,授权模式定义为password即可。
在这里插入图片描述
还需要在请求头中添加Basic验证信息,直接写id和secret即可
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.1.3 隐式授权模式

这种模式需要在验证服务器上进行登录操作,而不是直接请求Token,验证登陆地址http://localhost:8500/sso/oauth/authorize?client_id=web&response_type=token
response_type一定是token类型,这样才会返回Token。
请求上边的验证登陆地址则会进入登录页面。

在这里插入图片描述
登录之后出现错误,这是因为登陆后验证服务器需要将结果返回给客户端,所以需要提供客户端的回调地址,这样浏览器会被重定向到指定的回调地址并且请求中回携带Token信息,此时随便配置一个回调地址,
在这里插入图片描述
配置回调地址,然后重启
在这里插入图片描述
此时会要求进行授权,
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.1.4 授权码模式-最安全

这种方式和1.2.3的流程一样,但是请求的地址是code类型:http://localhost:8500/sso/oauth/authorize?client_id=web&response_type=code,访问该地址,因为在1.2.3已经登录过了,可以看到访问之后,依然会进入到回调地址,但是此时给的是授权码code了,不是直接给token。但是有时候可能需要token。
在这里插入图片描述

按照2.1之前的第四个授权码图示原来,需要携带授权码secret一起请求,才能拿到token,正常情况下是由回调的服务器进行处理,在postman中测试进行,复制刚得到的授权码,接口请求localhost:8500/sso/oauth/token
可以看到正常拿到token
在这里插入图片描述
以上四种基本的Token请求方式。

2.1.5 刷新令牌

当Token过期时,就可以使用这个refresh_token来申请一个新的Token。
在这里插入图片描述
重新请求
在这里插入图片描述
改为点击发送,出现异常
在这里插入图片描述
在这里插入图片描述
查看日志发现,还需要单独配置一个UserDetailsService,我们直接把Security中的实例注册为Bean。
在这里插入图片描述
然后再Endpoint中设置
在这里插入图片描述
在这里插入图片描述

添加完重启,重启之后token就没有了,需要重新申请以下。
访问http://localhost:8500/sso/oauth/authorize?client_id=web&response_type=code,先进行登录test,123456,然后授权获得code
在这里插入图片描述

在这里插入图片描述
获得code
在这里插入图片描述
获得token
在这里插入图片描述
访问接口刷新token
在这里插入图片描述

3. 单点登录客户端

前面已经将服验证服务器搭建完成了,下面实现单点登录,SpringCloud提供了客户端的直接实现,只需要添加一个注解和少量配置即可将我们的服务作为一个单点登录应用,使用的是第四张授权码模式。
这种模式只是将验证方式由原来的默认登陆形式改变为了统一在授权服务器登录的形式。

3.1 单点登录(基于@EnableOAuth2Sso实现)

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-oauth2</artifactId>
    <version>2.2.5.RELEASE</version>
</dependency>

在book-service中添加依赖
在这里插入图片描述
启动类添加注解
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
然后需要在配置文件中配置验证服务器相关的信息:

security:
  oauth2:
    client:
      #不多说了
      client-id: web
      client-secret: 654321
      #Token获取地址
      access-token-uri: http://localhost:8500/sso/oauth/token
      #验证页面地址
      user-authorization-uri: http://localhost:8500/sso/oauth/authorize
    resource:
      #Token信息获取和校验地址
      token-info-uri: http://localhost:8500/sso/oauth/check_token

在这里插入图片描述
启动book服务
在这里插入图片描述
访问,由于book服务是8301端口,需要将重定向地址也改为8301
在这里插入图片描述在这里插入图片描述

然后会登录跳转到授权页面
在这里插入图片描述
在这里插入图片描述
授权后访问成功
在这里插入图片描述
此时访问成功了但,但是用户信息是否也一并保存过来了,直接获取以下SpringSecurity的Context查看用户信息,获取方式和之前一样
在这里插入图片描述
再次访问book服务,输出用户信息
在这里插入图片描述
在这里插入图片描述
接着将所有的服务都使用这种方式进行验证,将重定向地址给所有服务都加上
在这里插入图片描述
将borrow-service,user-service都加上依赖,配置文件内容,和启动类的注释。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
配置完启动user和borrow服务和auth服务
在这里插入图片描述
此时访问user服务和book服务都是授权后可登录。但是此时三个服务session会互相占用,若访问完user服务,再访问user服务不会再次验证,但是若再访问book或其他服务就会需要再次验证。

这里有两个方案:一是和之前一样Session统一存储。二是设置context-path路径,每个服务单独设置,就不会互相占用了。

在这里插入图片描述
在这里插入图片描述
单点登录无法解决服务间调用的问题。

3.2 单点登录(基于@EnableResourceServer实现)

前面已经实现了将服务作为单点登录应用直接实现单点登录。但是如果是第三方访问,则我们就需要将服务作为资源服务了,作为资源服务就不会再提供验证的过长,而是直接要求请求时携带Token,而验证过程使用postman进行测试。
总之,与上边实现的相比,下边实现的访问过程只需要携带Token就能访问这些资源服务器了,客户端被独立了出来,用于携带Token去访问这些服务。

此时需要添加注解和少量配置
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
修改完配置和注解重启book-service,访问book服务,显示没有权限访问资源。

这是由于请求头中没有携带token信息,有两种方式可访问到资源
一:在URL后添加 access_token 请求参数,值为Token值
二:在请求头中添加 Authorization 值为 Bearer + Token值

在这里插入图片描述
在URL后添加 access_token 请求参数 此时通过密码模式访问拿到token
在这里插入图片描述

后缀参数加上获取的access_token即可访问
在这里插入图片描述在请求头中添加 Authorization 值为 Bearer + Token值
直接访问没有权限
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
然后可访问资源
在这里插入图片描述
到此,资源服务器就搭建完成

3.3 资源服务器深度自定义

编写一个配置类,使得用户授权了某个Scope才可以访问此服务。例如,必须有book作用域才能访问book-service服务
在这里插入图片描述

@Configuration
public class ResourceConfiguration extends ResourceServerConfigurerAdapter { //继承此类进行高度自定义

    @Override
    public void configure(HttpSecurity http) throws Exception {  //这里也有HttpSecurity对象,方便我们配置SpringSecurity
        http
                .authorizeRequests()
                .anyRequest().access("#oauth2.hasScope('lbwnb')");  //添加自定义规则
        //Token必须要有我们自定义scope授权才可以访问此资源
    }
}

添加完重启book-service
在这里插入图片描述
访问发现作用域不足
在这里插入图片描述
在这里插入图片描述重启后访问正常
在这里插入图片描述

实际上资源服务器完全没有必要将Security的信息保存在Session中,因为现在只需要将Token告诉资源服务器,那么资源服务器就可以联系验证服务器得到用户信息,不需要使用之前的Session存储机制了,所以会发现HttpSession中没有SPRING_SECURITY_CONTEXT,现在Security信息都是通过连接资源服务器获取。

在这里插入图片描述
但是目前每次访问都需要去验证一次,浪费资源,这种可以通过JTW去解决。
在这里插入图片描述
接着将所有服务都改为基于@EnableResourceServer方式实现,borrow-service和user-service的配置文件,启动类的注解都要修改

在这里插入图片描述
在这里插入图片描述
然后启动user、book、borrow服务,此时这三个服务都是资源服务。

访问user服务
在这里插入图片描述

访问borrow服务还是会出问题,因为远程调用也需要携带token,但是远程调用过程没有携带任何token’信息。因此需要想办法将用户传来的token信息在进行远程调用同时也携带上。因此可以直接使用OAuth2RestTemplate,它会在请求其他服务时携带当前请求的Token信息,它继承自RestTemplate,直接定义一个Bean

@Configuration
public class WebConfiguration {

    @Resource
    OAuth2ClientContext context;

    @Bean
    public OAuth2RestTemplate restTemplate(){
        return new OAuth2RestTemplate(new ClientCredentialsResourceDetails(), context);
    }
}

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
修改后重启borrow,然后访问borrow服务,此时正常调用。这样远程调用的时候就会也携带token信息
在这里插入图片描述

3.4 Nacos加入,通过Feign实现远程调用

加入依赖

## 给最外层pom添加
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
    <version>2021.0.1.0</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>
## 给每个服务添加
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

在这里插入图片描述
在这里插入图片描述配置Nacos服务
在这里插入图片描述
配置完启动nacos
在这里插入图片描述
在这里插入图片描述
三个服务分别添加配置
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
修改borrow服务service中的调用方式
在这里插入图片描述
配置完启动三个服务,进入nacos查看
在这里插入图片描述
访问borrow服务,此时已经加入了nacos、负载均衡。其中主要是要加入依赖和在WebConfiguration方法上加入@LoadBalanced注解
在这里插入图片描述

3.4.1 加入openfeign

在borrow服务添加依赖
在这里插入图片描述在borrow服务下写客户端
在这里插入图片描述
在这里插入图片描述

@FeignClient("book-service")
public interface BookClient {

    @RequestMapping("/book/{bid}")
    Book getBookById(@PathVariable("bid") int bid);
}
@FeignClient("user-service")
public interface UserClient {
    
    @RequestMapping("/user/{uid}")
    User getUserById(@PathVariable("uid") int uid);
}

在这里插入图片描述
在borrowServiceImpl直接注入
在这里插入图片描述
启动类加入注解
在这里插入图片描述
此时openfeign访问没有携带token。还会出现之前的访问borrow服务出错。此时需要添加配置。

feign:
  oauth2:
  	#开启Oauth支持,这样就会在请求头中携带Token了
    enabled: true
    #同时开启负载均衡支持
    load-balanced: true

在这里插入图片描述
重新启动borrow-service,此时接口调用带有token,则访问成功
在这里插入图片描述
在这里插入图片描述
但是每次访问一次就需要校验一次,若用户多了,服务器压力就很大。

3.5 使用JWT存储Token

官网https://jwt.io
在这里插入图片描述
JWT令牌的格式如下:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
Base64不是加密算法,只是一种信息的编码方式。

  public void test(){
      String str = "你们可能不知道只用20万赢到578万是什么概念";
    	//Base64不只是可以对字符串进行编码,任何byte[]数据都可以,编码结果可以是byte[],也可以是字符串
      String encodeStr = Base64.getEncoder().encodeToString(str.getBytes());
      System.out.println("Base64编码后的字符串:"+encodeStr);
  
      System.out.println("解码后的字符串:"+new String(Base64.getDecoder().decode(encodeStr)));
  }

在这里插入图片描述
在这里插入图片描述
这里使用最简单的一种方式,对称密钥,对验证服务器进行修改:

@Bean
public JwtAccessTokenConverter tokenConverter(){  //Token转换器,将其转换为JWT
    JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
    converter.setSigningKey("lbwnb");   //这个是对称密钥,一会资源服务器那边也要指定为这个
    return converter;
}

@Bean
public TokenStore tokenStore(JwtAccessTokenConverter converter){  //Token存储方式现在改为JWT存储
    return new JwtTokenStore(converter);  //传入刚刚定义好的转换器
}

在这里插入图片描述

@Resource
TokenStore store;

@Resource
JwtAccessTokenConverter converter;

private AuthorizationServerTokenServices serverTokenServices(){  //这里对AuthorizationServerTokenServices进行一下配置
    DefaultTokenServices services = new DefaultTokenServices();
    services.setSupportRefreshToken(true);   //允许Token刷新
    services.setTokenStore(store);   //添加刚刚的TokenStore
    services.setTokenEnhancer(converter);   //添加Token增强,其实就是JwtAccessTokenConverter,增强是添加一些自定义的数据到JWT中
    return services;
}

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
    endpoints
            .tokenServices(serverTokenServices())   //设定为刚刚配置好的AuthorizationServerTokenServices
            .userDetailsService(service)
            .authenticationManager(manager);
}

在这里插入图片描述
在这里插入图片描述
重启auth-service服务,通过密码模式获取token,此时返回的token是JWT令牌。可对其进行Base64解码
在这里插入图片描述
生成的access_token用base64解码查看,需要在".“前后分开解码。
第一段为jwt
在这里插入图片描述
第二段用户信息
在这里插入图片描述

然后对资源服务器进行配置;
在这里插入图片描述

security:
  oauth2:
    resource:
      jwt:
        key-value: lbwnb #注意这里要跟验证服务器的密钥一致,这样算出来的签名才会一致

在这里插入图片描述
然后在book-service,user-service都进行以上相应的修改,修改完重启对应服务,并加上token进行访问
在这里插入图片描述
user,book服务访问正常
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

vs2019配置libcurl环境

一、libcurl下载地址&#xff1a;curl - Download 二、解压下载的压缩包&#xff0c;进入projects\Windows\VC14目录 三、用vs2019打开curl-all.sln工程&#xff0c;选择LIB Debug&#xff0c;x64进行编译 编译后的文件为&#xff1a;curl-8.2.1\build\Win64\VC14\LIB Debug\li…

【c语言中的字符串相关方法介绍】

C语言中有许多字符串相关的函数&#xff0c;用于处理字符串的创建、修改、查找和比较等操作。以下是一些常见的字符串相关函数以及它们的使用方法&#xff1a; strlen&#xff08;字符串长度&#xff09;&#xff1a;用于计算字符串的长度&#xff0c;不包括字符串末尾的空字符…

【AI视野·今日Robot 机器人论文速览 第四十三期】Thu, 28 Sep 2023

AI视野今日CS.Robotics 机器人学论文速览 Thu, 28 Sep 2023 Totally 37 papers &#x1f449;上期速览✈更多精彩请移步主页 Interesting: &#x1f4da;****触觉力控学习策略,基于触觉的主动推理与力控用于小孔插入任务。提出了姿态控制与插入控制双策略模型。 (from 东京大学…

京东数据平台:2023年8月京东白酒行业品牌销售排行榜

鲸参谋监测的京东平台8月份白酒市场销售数据已出炉&#xff01; 根据鲸参谋平台的数据显示&#xff0c;今年8月份&#xff0c;白酒市场的销量为198万&#xff0c;环比下滑约6%&#xff0c;同比下滑不足1%&#xff1b;销售额为15亿&#xff0c;环比下滑约18%&#xff0c;同比则…

c++ | makefile | 编译 | 链接库

简单记一下 看着人家总结的挺好的 点这

面试问到MySQL模块划分与架构体系怎么办

面试问到Mysql模块划分与架构体系怎么办 文章目录 1. 应用层连接管理器&#xff08;Connection Manager&#xff09;安全性和权限模块&#xff08;Security and Privilege Module&#xff09; 2. MySQL服务器层2.1. 服务支持和工具集2.2. SQL Interface2.3. 解析器举个解析器 …

ChatGPT社交时代降临!Meta在三大平台,集成28个生成式AI!

9月28日&#xff0c;全球社交、科技巨头Meta&#xff08;前身是Facebook&#xff09;在官网宣布&#xff0c;在旗下的Instagram、WhatsApp和Messenger三大社交平台中&#xff0c;集成28个生成式AI聊天机器人。 据悉&#xff0c;这些AI机器人是基于Meta最新发布的大语言模型Lla…

力扣-349.两个数组的交集

Idea 使用两个哈希集合&#xff0c;其中一个用来存储第一个数组&#xff0c;第二个来存储两个数组的交集&#xff0c;因为集合自带去重功能&#xff0c;因此最后用数组来接收就好了 AC Code class Solution { public:vector<int> intersection(vector<int>& n…

自动化测试框架总结

前言 自动化测试框架是一套工具、库和规范的集合&#xff0c;用于支持和简化自动化测试的开发、执行和管理。 提供一种结构化的方法来编写、组织和执行自动化测试用例&#xff0c;并提供一些常用的功能和工具&#xff0c;例如测试用例管理、结果报告生成、测试数据管理、日志…

17周年庆第一弹|中秋·国庆双节大促购物指南,给力狂欢!

随着中秋和国庆双节的来临,百脑汇广州店为了满足消费者的购物需求,特别推出了本次17周年店庆月:双节大促购物指南。本指南将为您介绍百脑汇广州店的优惠购机活动、热门商品等等,帮助您在本次17周年店庆月中获得更好的体验。 百脑汇广州店17周年店庆月第一弹:中秋国庆双节大促中…

【面试经典 150 | 滑动窗口】串联所有单词的子串

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;两个哈希表方法二&#xff1a;滑动窗口 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一…

【图论C++】树的重心——教父POJ 3107(链式前向星的使用)

》》》算法竞赛 /*** file * author jUicE_g2R(qq:3406291309)————彬(bin-必应)* 一个某双流一大学通信与信息专业大二在读 * * brief 一直在竞赛算法学习的路上* * copyright 2023.9* COPYRIGHT 原创技术笔记&#xff1a;转载…

$nextTick解决echarts宽度固定为100%的问题

问题描述:vue+element项目中使用到了tab切换选项卡,其中有一个tab下的内容是echarts,出现了echarts宽度缩减为100px无法继承100%属性。 问题: echarts渲染时tab选项卡display为none,所以width:100%没有可继承项,被echarts自带方法切割成100px。 我他喵的解决这个问题还是…

给 shell 自定义快捷键

shell 快捷键原理 本质上对于 shell 来说只有输入输出&#xff0c;它不会监听你系统快捷键的&#xff0c;监听快捷键其实是终端模拟器的责任&#xff0c;他会将你输入的快捷键转换成字符串序列。当我们使用了类似 ctrl -> 这样的快捷键&#xff0c;shell 会根据你输入的字…

QT的ui设计中改变样式表的用法

在QT的ui设计中,我们右键会弹出一个改变样式表的选项,很多人不知道这个是干什么的。 首先我们来看下具体的界面 首先我们说一下这个功能具体是干嘛的, 我们在设置很多控件在界面上之后,常常都是使用系统默认的样式,但是当有些时候为了美化界面我们需要对一些控件进行美化…

进阶JS-内置构造函数

基本数据类型&#xff1a;string、number、boolean、undefined、null 引用类型:对象 其实字符串、数值、布尔等基本类型也都有专门的构造函数&#xff0c;这些我们称为包装类型。 JS中几乎所有的数据都可以基于构成函数创建。 const str andy//其实是const strnew String(a…

【EI会议征稿】第三届机械、建模与材料工程国际学术会议(I3ME 2023)

第三届机械、建模与材料工程国际学术会议&#xff08;I3ME 2023&#xff09; 2023 3rd International Conference on Mechanical, Modeling and Materials Engineering 第三届机械、建模与材料工程国际学术会议&#xff08;I3ME 2023&#xff09;将于2023年12月1-3日在中国长春…

一套成熟的Spring Cloud智慧工地平台源码,自主版权,开箱即用

智慧工地云平台源码 APP端PC端数据大屏端全套源码 自主版权&#xff0c;开箱即可项目使用 智慧工地利用移动互联、物联网、云计算、大数据等新一代信息技术&#xff0c;彻底改变传统施工现场各参建方的交互方式、工作方式和管理模式&#xff0c;为建设集团、施工企业、监理单位…

第二证券:券商近期关注点浮现 扎堆调研19只个股 上调旅游股评级

19只个股 被券商扎堆调研 东方财富Choice数据显现&#xff0c;9月以来券商保持高强度的调研节奏&#xff0c;19只个股获得超25家券商扎堆调研&#xff0c;首要会合在半导体、医药生物、新能源、机械设备等范畴。人气最高的股票分别是埃斯顿、周大生、南网科技、卫星化学、宁波…