Oauth2.0 认证

news2024/10/7 4:27:32

目录

前言

1.介绍

2.Oauth2.0过程详解 

3.Oauth 整合到 Spring Boot 实践 

4.方法及配置详解:

总结


前言

Oauth2.0 是非常流行的网络授权表准,已经广泛应用在全球范围内,比较大的公司,如腾讯等都有大量的应用场景。


1.介绍

Oauth2.0 全称是 Open Authorization,是一种开放授权协议。目前使用的版本是 2.0 版本,也就是 Oauth2.0,它主要用于授权认证环节。

从官网文档可知道 Oauth 具有如下特点:

  1. 需要第三方进行授权,会存储用户登录授权凭据。
  2. 服务器必须支持密码认证。
  3. 有限范围内获取所有者(用户)的部分数据。 

简而言之,就是用于第三方在用户授权的前提下获取用户的相关信息。而 Oauth2.0 的授权模式比较多,常用的有如下四种:

  1. 授权码模式:最常规的模式,适用于有服务器端的第三方应用(如网页应用)。在这种模式下,用户代理(如浏览器)首先被重定向到授权服务器进行身份验证,授权服务器通过用户代理回调客户端,并提供一个授权码。客户端随后会使用这个授权码向授权服务器后端请求访问令牌(access token),支持刷新的 token。
  2. Clinet 模式:适用于客户端应用直接访问它们自己的资源服务器,没有用户直接参与的场景。在这个模式中,客户端应用凭借自己的凭据(客户端ID及客户端密钥)向授权服务器请求访问令牌。其他应用或者程序通过 api 进行调用,获取对应的 token。
  3. 简化模式:用于没有服务器端能力的客户端应用,如 JavaScript 应用。在简化模式中,客户端通过用户代理直接从授权服务器获取访问令牌,不通过中间的授权码交换步骤。由于这种模式暴露了访问令牌,因此不如授权码模式安全。
  4. 密码模式 :如果用户对第三方应用高度信任(例如,设备操作系统或具备原生应用的第三方服务),则可以直接将用户名和密码提供给应用,应用使用这些凭据直接从授权服务器获取访问令牌。由于此流程涉及明文传递用户凭据,因此安全性较低。

总结:从中其实可以看出,最关键的部分就是这三方相互确认的过程。授权码模式就可以看成三方之间都不信任,所以需要不断地相互确认;而简化模式则可以看作授权服务器对第三方应用比较信任,表示直接就给了你我的令牌,你并不会拿我的令牌去做坏事,也就是说它们之间比较互信;密码模式则是资源拥有者对第三方应用比较信任,可以将自己的信息放心的放给第三方;客户端模式则可以看成三方都比较信任,不需要过多的验证,请求就给令牌就行了,比较适合我们内部的应用场景。

梳理 Oauth2.0 中有一个主线,就是三方参与者之间的信任程度

2.Oauth2.0过程详解 

前面我们对四个常见的模式进行了详细的了解,为了更加方便理解,对基本的过程再次进行详细解释。Oauth 的基本认正过程如图,分为三个角色:用户、第三方、以及认证服务器。

首先,用户去访问第三方应用,第三方应用引导用户进行授权,跳转到授权页面。用户进行授权后将数据传递给认证服务器,认证服务器返回 code 给第三方应用,第三方应用发起新的请求来获取访问授权令牌(access token),最后用户获取到授权结果。 

3.Oauth 整合到 Spring Boot 实践 

客户端凭证是最常用的认证方式之一。例如,微信授权就是这种方式,通过携带 access token 来获取用户资源。

新建Spring Boot 项目,实现方案是使用 SpringSecurity 和 Oauth2.0 模块,pom.xml 添加如下依赖:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
            <version>2.3.5.RELEASE</version>
        </dependency>

为了实现 Oauth 认证,需要对两方面进行配置,一是认证服务配置,包含 token 定义,用户客户端的信息以及授权服务和令牌服务。二是需要对资源服务进行配置,如资源访问权限设置,哪些需要 token 验证。

首先,编写认证服务配置,定义授权以及令牌服务。

package org.example.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

/**
 * 认证服务器类
 *
 * @author freejava
 */
@Configuration
//此注解不像其他的 Enable注解一样内部有 Component 注解
@EnableAuthorizationServer
public class MySuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private AuthorizationCodeServices authorizationCodeServices;

    //令牌访问安全策略
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        //用于表单方式提交 client_id,client_secret
        security.tokenKeyAccess("permitAll()")
                        .checkTokenAccess("permitAll()").
                allowFormAuthenticationForClients();
    }

    @Bean
    public PasswordEncoder noOpPasswordEncoder(){
        return NoOpPasswordEncoder.getInstance();
    }

    /**
     *  配置客户端信息 哪些客户端可以发送请求
     * @param clients 定义客户端信息的配置们,可以初始化客户端信息。
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
       clients.inMemory()
               //client_id
               .withClient("myClientId")
               // client_secret
               .secret(NoOpPasswordEncoder.getInstance().encode("123456"))
               //授权方式
               .authorizedGrantTypes("authorization_code", "password","client_credentials","implicit","refresh_token")
               .resourceIds("res1")//可以访问哪些资源
               //授权范围
               .scopes("all")//write
               .autoApprove(false)//false跳转到授权页面
               //加上验证回调地址
               .redirectUris("http://www.baidu.com");
    }

    @Autowired
    private ClientDetailsService clientDetailsService;


    // 令牌服务
    @Bean
    public AuthorizationServerTokenServices tokenService(){
        DefaultTokenServices services = new DefaultTokenServices();
        services.setClientDetailsService(clientDetailsService);
        services.setSupportRefreshToken(true);
        services.setTokenStore(tokenStore());
        services.setAccessTokenValiditySeconds(7200);//2小时
        services.setRefreshTokenValiditySeconds(259200);//刷新令牌默认有效期 3 天
        return services;
    }
    //设置授权码模式如何存储
    @Bean
    public AuthorizationCodeServices authorizationCodeServices() {
        return new InMemoryAuthorizationCodeServices();
    }
    private String SIGNING_KEY = "uaa123";
    //内存方式
    @Bean
    public TokenStore tokenStore(){
        return  new InMemoryTokenStore();//new JwtTokenStore(accessTokenConverter());
    }
   /* @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(SIGNING_KEY); //对称秘钥,资源服务器使用该秘钥来验证
        return converter;
    }*/

    /**
     * 定义授权和令牌服务
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        //super.configure(endpoints);
        endpoints.authenticationManager(authenticationManager)
                .authorizationCodeServices(authorizationCodeServices)//授权码服务
                .tokenServices(tokenService())//令牌管理服务
                .allowedTokenEndpointRequestMethods(HttpMethod.POST,HttpMethod.GET);//允许POST提交

    }
}

资源配置编写,先编写一个 Controller 文件,代码如下:

package org.example.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ResController {
    @GetMapping("/res/{id}")
    public String testOauth(@PathVariable String id) {
        return "Get the resource " + id;
    }
}

然后编写该资源的访问权限配置,代码如下:

package org.example.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;

/**
 * 用于拦截请求的配置类
 */
@Configuration
@EnableResourceServer
public class MyResourceServerConfigurer extends ResourceServerConfigurerAdapter {
    @Autowired
    private TokenStore tokenStore;

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        //这里重点注意
        resources.tokenStore(tokenStore).resourceId("res1");
    }


    /**
     * 用于拦截 http 请求
     * @param http
     * @throws Exception
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {

        http.csrf().disable().
                authorizeRequests()
                .antMatchers("/oauth/**").permitAll() // 允许所有人访问 /oauth/* 下面的内容。
                .anyRequest().authenticated(); // 其他所有请求都需要认证。
        /*http.authorizeRequests().anyRequest()
                .authenticated();
                        //("/res/**").authenticated();*/
    }
}

为授权码模式编写一个webconfig:

package org.example.config;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * @author Administrator
 * @version 1.0
 **/
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    //认证管理器
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    //安全拦截机制(最重要)
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests()
                .antMatchers("/orther/**").hasAnyAuthority("p1")
                .antMatchers("/login*").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin();

    }
}

通过 Postman 进行测试,访问 localhost:8080/res/1 会返回一个 unauthorized 的错误返回,这里需要传递 access token,所以需要先请求获取 access token 的接口 /oauth/token,之后再用该token进行请求即可。 

4.方法及配置详解:

ClientDetailsServiceConfigurer 详解: 

ClientDetailsServiceConfigurer 是用于配置客户端详细信息服务的类。客户端详细信息服务定义了客户端(应用程序)的信息,这包括客户端ID、客户端密钥、授权模式、令牌有效期以及重定向的URI等信息。客户端详细信息可以通过硬编码、数据库等方式来存储和管理。

以下是 ClientDetailsServiceConfigurer 的一些常用方法:

  1. inMemory()
    在内存中配置客户端存储,主要用于测试或简单应用程序,不适合生产使用。

  2. jdbc(DataSource dataSource)
    使用 JDBC 连接数据库,并在数据库中维护客户端信息。

  3. withClient(String clientId)
    创建新的客户端,并设置其客户端id。

  4. secret(String secret)
    设置客户端的密钥。对于使用Spring Security 5的应用程序,需要注意密码存储格式,通常是 {bcrypt}{noop} 等。

  5. redirectUris(String… redirectUris)
    设置客户端的重定向URI,这些URI在OAuth2授权码模式下使用。

  6. authorizedGrantTypes(String… authorizedGrantTypes)
    设置客户端允许的授权模式,如 authorization_codepasswordrefresh_tokenclient_credentials

  7. authorities(String… authorities)
    为客户端设置Spring Security的权限。

  8. scopes(String… scopes)
    设置客户端的作用域(scope),限定客户端的访问范围。

  9. accessTokenValiditySeconds(int accessTokenValiditySeconds)
    设置访问令牌的有效时间(以秒计)。

  10. refreshTokenValiditySeconds(int refreshTokenValiditySeconds)
    设置刷新令牌的有效时间(以秒计)。

  11. additionalInformation(Map<String, ?> additionalInformation)
    设置一个包含其他客户端详细信息的Map。

  12. autoApprove(boolean autoApprove)
    如果设置为true,则不需要用户在授权阶段进行手动批准。

  13. autoApprove(String… scopes)
    指定特定范围的自动批准。

  14. resourceIds(String… resourceIds)
    限定客户端可以访问的资源服务器的ID。 

AuthorizationServerEndpointsConfigurer详解:

默认得到访问路径:

  • /oauth/authorize: 授权端点
  • /oauth/token : 令牌端点。
  • /loauth/confirm_access : 用户确认授权提交端点。
  • /loauth/error: 授权服务错误信息端点。
  • /oauth/check_token : 用于资源服务访问的令牌解析端点
  • /oauth/token_key : 提供公有密匙的端点,如果你使用JWT令牌的话. 

AuthorizationServerEndpointsConfigurer是Spring Security OAuth2中用于定义授权服务器端点配置的类,它允许你定义与认证相关的各种参数和实现。也就是配置令牌的访问端点(发放令牌的地址)和令牌服务(如何发放),下面是一些 AuthorizationServerEndpointsConfigurer 的主要配置方法,以及它们的用途:

  1. authenticationManager(AuthenticationManager authenticationManager)
    设置认证管理器。在password授权模式下,需要配置此项来验证用户的用户名和密码。

  2. userDetailsService(UserDetailsService userDetailsService)
    设置用户细节服务。如果你设置了一个自定义的用户细节服务,可以通过这个方法来配置。

  3. authorizationCodeServices(AuthorizationCodeServices authorizationCodeServices)
    设置授权码服务。用于authorization_code授权类型。这能够改变默认的授权码存储方式(通常是内存)。

  4. tokenStore(TokenStore tokenStore)
    设置令牌存储方式。可以使用各种不同的存储方式,如内存、JDBC或JWT tokens。

  5. accessTokenConverter(AccessTokenConverter accessTokenConverter)
    设置访问令牌转换器。例如,使用JWT token时,可以配置一个JwtAccessTokenConverter

  6. tokenEnhancer(TokenEnhancer tokenEnhancer)
    设置令牌增强器。可以用来扩展JWT token内容。

  7. approvalStore(ApprovalStore approvalStore)
    设置批准存储。这跟token的保存方式类似,定义了用户批准记录的存储方式。

  8. reuseRefreshTokens(boolean reuseRefreshTokens)
    设置是否复用refresh tokens。默认为true,即当新的access token被创建后,原始的refresh token将会被复用。

  9. refreshTokenGranter(TokenGranter refreshTokenGranter)
    设置自定义的refresh token授权者。

  10. grantTypes(TokenGranter tokenGranter)
    设置自定义授权类型,可以添加或覆盖默认的授权类型来扩展功能。

  11. tokenValidator(OAuth2TokenValidator<Jwt> tokenValidator)
    在使用JWT时设置令牌验证器,用以验证JWT的有效性。

  12. tokenServices(DefaultTokenServices tokenServices)
    设置token服务的实例。这个服务负责创建和管理OAuth2 tokens。

  13. exceptionTranslator(WebResponseExceptionTranslator<OAuth2Exception> exceptionTranslator)
    设置异常翻译器。用来定义认证异常的响应格式。

  14. requestFactory(OAuth2RequestFactory requestFactory)
    设置OAuth2请求工厂。这允许你插入自定义逻辑来解析传入的请求。 

AuthorizationServerSecurityConfigurer :

用来配置令牌端点的安全约束,比如哪些人可以访问。

ResourceServerSecurityConfigurer详解

ResourceServerSecurityConfigurer 是 Spring Security OAuth2 中用于配置资源服务器的安全细节的一个类。它允许你设置一些关于资源服务器的关键配置,比如 tokenStore、resourceId 和 tokenServices 等。下面是一些 ResourceServerSecurityConfigurer 的常用方法及其简要说明:

  1. tokenStore(TokenStore tokenStore)
    设置用于读取令牌信息的 TokenStore。这个 TokenStore 被资源服务器用来解码访问令牌。常见的实现是 JdbcTokenStoreJwtTokenStore 和 InMemoryTokenStore

  2. resourceId(String resourceId)
    设置此资源服务器的资源ID。这通常用于客户端请求的 Scope 限制,以及在多个资源服务器存在时加以区分。

  3. tokenServices(TokenServices tokenServices)
    设置 ResourceServerTokenServices 实例,这是用来解码访问令牌的另一种方式。如果你的令牌是 JWT,则可以提供 JwtTokenServices

  4. tokenExtractor(TokenExtractor tokenExtractor)
    设置用于提取访问令牌的 TokenExtractor。默认情况下,Spring OAuth2 使用 BearerTokenExtractor 来处理来自请求头或请求参数的 Bearer 令牌。

  5. authenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint)
    定制用于处理认证错误的 AuthenticationEntryPoint。通常情况下,这用于处理资源服务器返回给客户端的401响应。

  6. accessDeniedHandler(AccessDeniedHandler accessDeniedHandler)
    设置自定义 AccessDeniedHandler 以处理接收到访问被拒绝时的情况。这通常用来自定义服务器对403 Forbidden响应的处理。

  7. stateless(Boolean stateless)
    设置此资源服务器是否只关心无状态请求应答。这确定了资源服务器是否会在请求间创建 HttpSession

  8. authenticationManager(AuthenticationManager authenticationManager)
    设置 AuthenticationManager。如果需要,可以用来登陆用户或验证用户的访问令牌。

  9. eventPublisher(ApplicationEventPublisher eventPublisher)
    设置 ApplicationEventPublisher 以发布认证事件。这可以用来记录认证成功或者失败等事件。


总结

OAuth 2.0 是一个用于授权的开放标准,由 IETF OAuth 工作组于 2012 年发布。它允许用户授权第三方应用访问其在某一服务上的信息,而无需将用户名和密码提供给第三方应用,大大促进了当前互联网间的信息共享。

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

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

相关文章

Qt工程文件分离、Qtimer定时器、Qt Creator 常用快捷键

Qt 工程文件分离 不含 UI 的文件分离 以堆栈窗体的代码为例。 firstpagewidget.h #ifndef FIRSTPAGEWIDGET_H #define FIRSTPAGEWIDGET_H#include <QtWidgets> // 记得修改class firstPageWidget : public QWidget {Q_OBJECT public:explicit firstPageWidget(QW…

Python表单处理

目录 通过Flask处理表单 通过Flask-WTF处理表单 通过Flask-WTF验证表单 通过Flask处理表单 表单是在网页中搜集用户信息的各种表单控件的集合区域&#xff0c;表单控件包括文本框、单选框、复选框、提交按钮等&#xff0c;用于实现客户端和服务器端之间的数据交互。 利用F…

uniapp各种小程序分享 share - 主要流程 - 微信、抖音、快手、qq

参考 小程序环境 分享 | uni-app官网uni-app,uniCloud,serverless,分享,uni.share(OBJECT),分享到微信聊天界面示例代码,分享到微信朋友圈示例代码,uni.share 在App端各社交平台分享配置说明,uni.shareWithSystem(OBJECT),plus.share.sendWithhttps://uniapp.dcloud.net.cn/a…

监控pod 容器外网请求网络带宽,过滤掉内网、基于k8spacket开发

首先安装k8spacket 安装k8spacket遇到问题&#xff0c;下载插件一直能不能下载成功&#xff0c;pod不能启动。所有手动下载处理。 helm repo add k8spacket https://k8spacket.github.io/k8spacket-helm-chart helm pull k8spacket/k8spacket打开values.yaml 文件 手动下载插…

机器视觉相机镜头光源选型

镜头选型工具 - HiTools - 海康威视 Hikvisionhttps://www.hikvision.com/cn/support/tools/hitools/cl8a9de13648c56d7f/ 海康机器人-机器视觉产品页杭州海康机器人股份有限公司海康机器人HIKROBOT是面向全球的机器视觉和移动机器人产品及解决方案提供商&#xff0c;业务聚焦于…

HCIP —— BGP 基础 (下)

BGP 的状态机 --- 建立对等体之间的TCP会话&#xff1a;指定建立对等体的对象 六种状态机 Idle状态 Idle 等待状态&#xff08;相当于OSPF的down状态&#xff09;--- 采用TCP单播建邻 Idle 状态下&#xff0c;启动BGP协议后必须指定建立对等体的目标之后&#xff0c;才能进入…

【vSphere | VM】虚拟机自定义规范Ⅲ —— 创建 Linux 虚拟机自定义规范

目录 4. 创建关于Linux系统的虚拟机自定义规范4.1 新建 Linux 虚拟机自定义规范&#xff08;1&#xff09;名称和目标操作系统&#xff08;2&#xff09;计算机名称&#xff08;3&#xff09;时区&#xff08;4&#xff09;自定义脚本&#xff08;5&#xff09;网络&#xff08…

shell脚本发邮件

首先下载mailx [rootemail ~]# yum -y install mailx 修改配置文件 [rootemail ~]# vim /etc/mail.rc set from2760592774qq.com #你的QQ邮箱或者网易邮箱其他邮箱 set smtpsmtp.qq.com #QQ邮箱就写这个&#xff0c;网易邮箱写smtp.163.com set smtp-auth-user27605927…

微型5G智能网关助力打造智能清洁机器人

智能机器人不断融入我们的生活&#xff0c;提供了越来越多样化的服务&#xff0c;例如专用于卫生清洁的机器人&#xff0c;就已经广泛应用于酒店、体育馆、大型商场、写字楼、工地等各种场景&#xff0c;相较于人工&#xff0c;机器人在此类具有高度重复性、劳动量大的工作中具…

WMS条码扫描管理:实现仓库管理的高效与精准

随着企业运营的日益复杂化&#xff0c;仓库管理系统&#xff08;WMS&#xff09;已成为许多企业实现物流和供应链优化的关键工具。其中&#xff0c;条码扫描管理是WMS系统的重要组成部分&#xff0c;它对于提高仓库操作效率、增强库存准确性以及优化整体运营具有显著意义。本文…

GPT-4V 在机器人领域的应用

在科技的浩渺宇宙中&#xff0c;OpenAI如一颗璀璨的星辰&#xff0c;于2023年9月25日&#xff0c;以一种全新的方式&#xff0c;向世界揭示了其最新的人工智能力作——GPT-4V模型。这次升级&#xff0c;为其旗下的聊天机器人ChatGPT装配了语音和图像的新功能&#xff0c;使得用…

EMC VNX Unified存储NAS控制台常见问题解答

每次遇到VNX unfied的case就是一坨屎&#xff0c;很多客户根本不理解什么是Unifed storage&#xff0c;EMC的Clariion中端存储系统还分Block和Unified的产品。这个blog就是简单介绍一下VNX Unified存储的管理控制台&#xff0c;英文是 control station, 简称为CS。 顾名思义&a…

vivado时序方法检查10

TIMING-41 &#xff1a; 内部管脚上定义的前向时钟无效 前向时钟 <clock_group> 是在管脚 <netlist_element> 上定义的 &#xff0c; 而不是在端口 <netlist_element> 上定义的。 描述 前向时钟是在连接到输出端口的叶节点管脚上定义的 &#xff0c…

【python可视化系统源码】基于爬虫与可视化的电影推荐系统课题背景、目的、意义、研究思路、研究方法

该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程等学习内容。 目录 一、项目介绍&#xff1a; 二、文档学习资料&#xff1a; 三、模块截图&#xff1a; 四、开发技术与运行环境&#xff1a; 五、代码展示&#xff1a; 六、数据库表截图&#xff1a…

小红书品牌投放须知,家居产品软文怎么写?

家居产品软文&#xff0c;是一种展示家居产品的文案写作形式。优秀的家居产品软文能够通过引人入胜的文字&#xff0c;吸引受众的注意力并激发他们选购家居产品的兴趣。今天我们来为大家分享一下小红书品牌投放须知&#xff0c;家居产品软文怎么写&#xff1f; 一、关键词布局 …

【数值计算方法(黄明游)】函数插值与曲线拟合(一):Lagrange插值【理论到程序】

​ 文章目录 一、近似表达方式1. 插值&#xff08;Interpolation&#xff09;2. 拟合&#xff08;Fitting&#xff09;3. 投影&#xff08;Projection&#xff09; 二、Lagrange插值1. 天书2. 人话拉格朗日插值方法a. 线性插值&#xff08;n1&#xff09;基本思想线性插值与线…

使用FFMPEG转码,转单声道,转标准WAV,转PCM

本文为使用FFMPEG命令行的方式处理音频&#xff0c;来获取想要得到的音频文件。 零、使用命令行查看编码封装信息 格式&#xff1a;ffprobe.exe -show_format inputfile 例子&#xff1a;ffprobe.exe -show_format .\stereo_44_16bit.wav 运行结果为下图&#xff1a; 如图可…

实现:切换页面切换标题,扩展 vue-router 的类型

布局容器-页面标题 网址&#xff1a;https://router.vuejs.org/zh/guide/advanced/meta 给每一个路由添加 元信息 数据 router/index.ts const router createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{ path: /login, component: () > im…

用什么台灯对眼睛最好?考公护眼台灯推荐

之前我一直觉得&#xff0c;孩子近视&#xff0c;是因为玩手机太多&#xff0c;看电子产品的时间过长&#xff0c;但后来控制孩子看电子产品时间的触底反弹与越来越深的度数告诉我&#xff0c;孩子近视的真正原因&#xff0c;我根本没有找到&#xff0c;后来看到一篇报告&#…

【Windows】安装 Apache服务 -- 实操详细版

&#x1f468;‍&#x1f393;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; &#x1f40b; 希望大家多多支…