【通俗易懂介绍OAuth2.0协议以及4种授权模式】

文章目录

    • 一.OAuth2.0协议介绍
    • 二.设计来源于生活
    • 三.关于令牌与密码的区别
    • 四.应用场景
    • 五.接下来分别简单介绍下四种授权模式吧
      • 1.客户端模式
        • 1.1 介绍
        • 1.2 适用场景
        • 1.3 时序图
      • 2.密码模式
        • 2.1 介绍
        • 2.2 适用场景
        • 2.3时序图
      • 3.授权码模式
        • 3.1 介绍
        • 3.2 适用场景
        • 3.3 时序图
      • 4.简化模式
        • 4.1 介绍
        • 4.2 适用场景
        • 4.3 时序图
      • 5. token刷新模式
        • 5.1 介绍
        • 5.2 适用场景
        • 5.3 时序图
    • 六.关键配置说明
      • 1.认证服务器配置类
      • 2.资源服务器配置类
    • 七.简单测试
    • 八.小结

一.OAuth2.0协议介绍

‌OAuth 2.0是一种开放标准的授权协议‌,设计用于授权一个第三方应用访问用户在另一个应用程序中的受保护资源,而无需提供用户名和密码。这种协议允许用户安全地分享他们的数据资源,同时保持对其数据的控制。OAuth 2.0在现代互联网应用中被广泛使用,例如我们的微信开放平台,微博开发平台,都能常见OAuth2.0的身影。
协议特点:

  1. 简单:不管是OAuth服务提供者还是应用开发者,都很易于理解与使用;
  2. 安全:没有涉及到用户密钥等信息,更安全更灵活;
  3. 开放:任何服务提供商都可以实现OAuth,任何软件开发商都可以使用OAuth;

二.设计来源于生活

之前看到过一篇文章介绍的生活场景,可以方便大家理解。
快递员问题:

  1. 比如咱们住在一个小区里面,小区有门禁系统,进入小区我们作为业主也需要输入账号密码、或者刷卡来确认业主身份无误才能进入。
  2. 但是我们平常点外卖、网购。每天都有快递员来送货,他们没有我们业主的账号密码进不来小区,但是我又不想专门跑到门禁处去拿,所以我必须找到一个办法,让快递员通过门禁系统进入小区,交到我手里。
  3. 如果我把自己的密码,告诉快递员,他就拥有了与我同样的权限,这样好像不太合适。万一我想取消他进入小区的权力,也很麻烦,我自己的密码也得跟着改了,还得通知其他的快递员。
  4. 有没有一种办法,让快递员能够自由进入小区,又不必知道小区居民的密码,而且他的唯一权限就是送货,其他需要密码的场合,他都没有权限?

于是就有了咱们的OAuth2.0开放标准授权协议。授权服务器(门禁系统) 授权一个第三方应用(快递员、外卖员等等) 访问用户(资源所有者)在资源服务器(小区内)的资源,比如进入小区的权利。

基于OAuth2.0开发标准协议,咱们的门禁系统也升级了:

  1. 在门禁系统那里,加了个申请授权按钮:快递员/外卖员 可以输入他的工号(提前在我们这边备案了,我们知道他编号的正确性),然后按这个按钮去申请授权。
  2. 他按下申请授权按钮以后,业主(也就是我)的手机就会跳出对话框:有人正在要求授权,并附带显示该快递员的姓名、工号和所属的快递公司,我确认没问题就点击确认授权按钮.
  3. 门禁系统知道我同意给予他进入小区的授权,向快递员显示一个进入小区的令牌(access token)。令牌就是类似密码的一串数字,只在一定时期内有效。
  4. 快递员向门禁系统输入令牌,进入小区,从而就可以把快递或者外卖交到我手里啦!

有人可能会问,为什么不是远程为快递员开门,而要为他单独生成一个令牌?这是因为快递员可能每天都会来送货,第二天他还可以复用这个令牌。另外,假如小区有多重门禁,快递员可以使用同一个令牌通过它们。

三.关于令牌与密码的区别

令牌(token)与密码(password)的作用是一样的,都可以进入系统,但是有三点差异。
(1)令牌是短期的,到期会自动失效,用户自己无法修改。密码一般长期有效,用户不修改,就不会发生变化。

(2)令牌可以被数据所有者撤销,会立即失效。以上例而言,屋主可以随时取消快递员的令牌。密码一般不允许被他人撤销。

(3)令牌有权限范围(scope),比如只能进小区的二号门。对于网络服务来说,只读令牌就比读写令牌更安全。密码一般是完整权限。

上面这些设计,保证了令牌既可以让第三方应用获得权限,同时又随时可控,不会危及系统安全。这就是 OAuth 2.0 的优点

注意,只要知道了令牌,就能进入系统。系统一般不会再次确认身份,所以令牌必须保密,泄漏令牌与泄漏密码的后果是一样的。 这也是为什么令牌的有效期,一般都设置得很短的原因

OAuth 2.0 对于如何颁发令牌的细节,规定得非常详细。
有四种方式进行授权:客户端模式、密码模式、授权码模式、简化模式(也叫隐式模式)。

四.应用场景

OAuth 2.0 在许多不同的应用场景中都能够发挥作用,尤其是那些涉及到第三方应用程序访问用户数据或资源的情况。
以下是一些常见的 OAuth 2.0 应用场景:

  • 比如我们京东商城通过微信授权方式登录,获取微信用户信息等等。
  • 社交媒体登录:许多网站和应用程序允许用户使用其社交媒体账户(如Facebook、Google、Twitter等)进行登录。OAuth2.0 可以用于授权第三方应用访问用户的社交媒体数据,如好友列表、社交活动等。
  • 第三方应用集成:用户可能使用多个不同的应用和服务,例如电子邮件、日历、云存储等。OAuth 2.0可以用于实现单一的登录授权,使用户能够在多个应用之间共享数据,而无需在每个应用中都输入凭证。
  • 医疗保健应用:在医疗保健领域,患者的健康数据可能由多个医疗应用和机构共享。OAuth 2.0可以用于确保授权的数据访问,同时保护患者隐私。

这些只是 OAuth 2.0 可能应用的一些例子。基本上任何需要实现安全的第三方应用程序访问用户数据或资源的情况下,OAuth 2.0 都可能是一个合适的解决方案。

五.接下来分别简单介绍下四种授权模式吧

1.客户端模式

1.1 介绍

客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行授权。客户端模式是安全级别最低而且要求授权服务器对客户高度信任的模式,因为客户端向授权服务器请求认证授权的过程中,至始至终都没有用户的参与,未经过用户允许,客户端凭提供自己在授权服务器注册的信息即可在授权服务器完成认证授权,而客户端获得认证授权以后,则拥有从资源服务器操作用户数据的权限。

1.2 适用场景

这种模式一般应用于公司内部系统或者有着高度保密责任的合作伙伴之间的对接。

1.3 时序图

在这里插入图片描述

  1. 客户端首先在认证服务器注册好客户端信息。
  2. 认证服务器存储维护客户端信息。
  3. 客户端带上client_id、client_secret、grant_type(写死client_credentials)等参数向认证服务器发起获取token 请求。
  4. 认证服务器校验客户端信息,校验通过,则发放令牌(access_token),校验失败,则返回异常信息。
  5. 客户端成功获取到令牌(access_token)后,就可以带着令牌去访问资源服务器了。

2.密码模式

2.1 介绍

如果你高度信任某个应用,也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为"密码模式"(password)。
密码模式是一种安全级别较低而且要求资源拥有者(用户)完全信任客户端的模式,该模式可以理解为在客户端模式的基础上增加了对用户的账号、密码在认证服务器进行校验的操作,是客户端代理用户的操作。在 OAuth 2.1 中,密码模式已经被废除,在第三方平台上,使用密码模式,对于用户来说是一种非常不安全的行为,假设某平台客户端支持 QQ 登录,用户使用自己 QQ 的账号、密码在该平台上输入进行登录,则该平台将拥有用户 QQ 的账号、密码,对于用户来说,将自己 QQ 的账号、密码提供给第三方平台,这种行为是非常不安全的。

2.2 适用场景

密码模式一般适合应用在自己公司内部使用的系统和自己公司的 app 产品:例如一些 ERP、CRM、WMS 系统,因为都是自己公司的产品,这种情况下就不存在用户提供账号、密码给第三方客户端进行代理登录的情形了。

2.3时序图

在这里插入图片描述
1:客户端首先在认证服务器注册好客户端信息。
2:认证服务器存储维护客户端信息。
3:用户提供认证平台的账号、密码给客户端(这里的客户端可以是浏览器、APP、第三方应用的服务器)。
4:客户端带上 client_id、client_secret、grant_type(写死password)、username、password 等参数向认证服务器发起获取 token 请求。
5:认证服务器校验客户端信息,校验失败,则返回异常信息,校验通过,则往下继续校验用户验账号、密码。
6:认证服务器校验用户账号、密码,校验通过,则发放令牌(access_token),校验失败,则返回异常信息。
7:客户端成功获取到令牌(access_token)后,就可以带着令牌去访问资源服务器了。

3.授权码模式

3.1 介绍

授权码(authorization code)方式,指的是第三方应用先申请一个授权码,然后再用该授权码获取令牌
授权码模式是 OAuth 2.0 协议中安全级别最高的一种认证模式,他与密码模式一样,都需要使用到用户的账号信息在认证平台的登录操作,但有所不同的是,密码模式是要求用户直接将自己在认证平台的账号、密码提供给第三方应用(客户端),由第三方平台进行代理用户在认证平台的登录操作;而授权码模式则是用户在认证平台提供的界面进行登录,然后通过用户确认授权后才将一次性授权码提供给第三方应用,第三方应用拿到一次性授权码以后才去认证平台获取 token。

3.2 适用场景

目前市面上主流的第三方验证都是采用这种模式,比如微信授权京东登录,微信授权某app登录,凡是设计第三方授权的基本都是采用这种模式。

3.3 时序图

在这里插入图片描述
1:客户端首先在认证服务器注册好客户端信息。
2:认证服务器存储维护客户端信息。
3:用户在客户端上发起登录。
4:向认证服务器发起认证授权请求,例如http://localhost:9000/auth/oauth/authorize?client_id=xxx&response_type=code&scope=message.read&redirect_uri=http://www.baidu.com,注意,此时参数不需要client_secret。
5:认证服务器带上客户端参数,将操作引导至用户授权确认页面,用户在该页面进行授权确认操作。
6:用户在授权页面选择授权范围,点击确认提交,则带上客户端参数和用户授权范围向认证服务器获取授权码。注意,此处操作已经脱离了客户端。
7:认证服务器校验客户端信息和授权范围(因为客户端在认证平台注册的时候,注册信息包含授权范围,如果用户选择的授权范围不在注册信息包含的范围内,则将因权限不足返回失败)。
8:校验通过,将授权码拼接到客户端注册的回调地址返回给客户端
9:客户端拿到认证服务器返回的授权码后,带上客户端信息和授权码向认证服务器换取令牌(access_token)。
10:认证服务器校验授权码是否有效,如果有效,则返回令牌(access_token);如果无效,则返回异常信息。
11:客户端成功获取到令牌(access_token)后,就可以带着令牌去访问资源服务器了。

4.简化模式

4.1 介绍

简化模式(也叫隐式模式)是相对于授权码模式而言的,对授权码模式的交互做了一下简化,省去了客户端使用授权码去认证服务器换取令牌(access_token)的操作,即用户在代理页面选择授权范围提交授权确认后,认证服务器通过客户端注册的回调地址直接就给客户端返回令牌(access_token)了

4.2 适用场景

这种方式把令牌直接传给前端,是很不安全的。因此,只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间(session)有效,浏览器关掉,令牌就失效了。

4.3 时序图

在这里插入图片描述
1:客户端首先在认证服务器注册好客户端信息。
2:认证服务器存储维护客户端信息。
3:用户在客户端上发起登录。
4:向认证服务器发起认证授权请求,例如http://localhost:9000/auth/oauth/authorize?client_id=xxx&response_type=token&scope=message.read&redirect_uri=http://www.baidu.com,注意,此时参数不需要 client_secret。
5:认证服务器带上客户端参数,将操作引导至用户授权确认页面,用户在该页面进行授权确认操作。
6:用户在授权页面选择授权范围,点击确认提交,则带上客户端参数和用户授权范围向认证服务器获取令牌(access_token)。注意,此处操作已经脱离了客户端。
7:认证服务器校验代理页面提交的参数信息,校验通过,则将令牌(access_token)拼接到客户端注册的回调地址返回给客户端;校验失败,则返回异常信息。
8:客户端成功获取到令牌(access_token)后,就可以带着令牌去访问资源服务器了。

5. token刷新模式

5.1 介绍

OAuth 2.0 允许用户自动更新令牌。token刷新模式是对 access_token 过期的一种补办操作,这种补办操作,减少了用户重新操作登录的流程。OAuth 2.0 在给客户端颁发 access_token 的时候,同时也给客户端发放了 refresh_token,而 refresh_token 的有效期要远大于 access_token 的有效期。当客户端带着已过期的 access_token 去访问资源服务器中受保护的资源时,将会访问失败,此时就需要客户端使用 refresh_token 去获取新的 access_token。客户端端获取到新的 access_token 后,就可以带上他去访问资源服务器中受保护的资源了。

5.2 适用场景

需要延长token使用时间,token过期无感刷新等等

5.3 时序图

在这里插入图片描述
1:客户端向认证服务器请求认证授权。
2:认证服务器存返回 access_token、refresh_token、授权范围、过期时间。
3:access_token 过期后,客户端仍旧带着过期的 access_token 去请求资源服务器中受保护的资源。
4:资源服务器提示客户端,这是非法的 access_token。
5:客户端使用 refresh_token 向认证服务器获取新的 access_token。
6:认证服务器校验 refresh_token 的有效性,校验通过,则给客户端颁发新的 access_token;校验失败,则返回异常信息。
7:客户端成功获取到新的 access_token 后,就可以带着新的 access_token 去访问资源服务器了。

六.关键配置说明

1.认证服务器配置类

  • 以下是认证服务器配置类里面配置的相关说明,继承并且实现AuthorizationServerConfigurerAdapter(认证服务配置适配器类),里面有3个关键的configure方法待我们去重写。
@Configuration
@EnableAuthorizationServer
@EnableConfigurationProperties(value = JwtCAProperties.class)
public class TulingAuthServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private TulingUserDetailService tulingUserDetailService;

    @Autowired
    private JwtCAProperties jwtCAProperties;

    /**
     * 方法实现说明:我们颁发的token通过jwt存储
     */
    @Bean
    public TokenStore tokenStore(){
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();

        // 配置jwt的签名
        // converter.setSigningKey("123123");

        //配置jwt的密钥, 使用RSA非对称加密
        converter.setKeyPair(keyPair());
        return converter;
    }

    @Bean
    public KeyPair keyPair() {
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource(jwtCAProperties.getKeyPairName()), jwtCAProperties.getKeyPairSecret().toCharArray());
        return keyStoreKeyFactory.getKeyPair(jwtCAProperties.getKeyPairAlias(), jwtCAProperties.getKeyPairStoreSecret().toCharArray());
    }

    @Bean
    public TulingTokenEnhancer tulingTokenEnhancer() {
        return new TulingTokenEnhancer();
    }

    /**
     * 方法实现说明:
     * 客户端具体信息服务配置: 就是配置这些客户端信息存到哪,内存里面还是数据库oauth_client_details表里面,认证服务器才能找到这些客户端并且颁发token
     * 这里是基于jdbc,注入JdbcClientDetailsService,也就是我们的客户端信息需要存入oauth_client_details表里面才能验证通过。
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(clientDetails());
         /**
         *基于内存方式存储客户端信息
        clients.inMemory()
                //配置client_id
                .withClient("client")
                //配置client-secret
                .secret(passwordEncoder.encode("123123"))
                //配置访问token的有效期
                .accessTokenValiditySeconds(3600)
                //配置刷新token的有效期
                .refreshTokenValiditySeconds(864000)
                //配置redirect_uri,用于授权成功后跳转
                .redirectUris("http://www.baidu.com")
                //配置申请的权限范围
                .scopes("all")
		        // 配置grant_type,表示授权类型:authorization_code: 授权码模式, implicit: 简化模式 ,
		        // password: 密码模式, client_credentials: 客户端模式, refresh_token: 更新令牌
                .authorizedGrantTypes("authorization_code","implicit","password","client_credentials","refresh_token");
                */
    }

    /**
     * 方法实现说明:用于查找我们第三方客户端信息是否在数据库表:oauth_client_details里面,
     * 只有配置在了表中的client_id和secrete才能获取token、token_key等等
     */
    @Bean
    public ClientDetailsService clientDetails() {
        return new JdbcClientDetailsService(dataSource);
    }

    /**
     * 方法实现说明:授权服务器端点的配置:
     * token怎么存储,OAuth2帮我们实现了 内存存储、jdbc、jwt、jwk、redis 存储。我们需要指定使用
     * token需要带什么信息(增强)、
     * 配置自己的UserDetailsService实现spring-security的UserDetailsService 用于进行用户信息检查
     * 密码模式下需要传入认证管理器,注入认证管理器,使用spring-security里面WebSecurityConfigurerAdapter里的authenticationManagerBean()构造的AuthenticationManagerDelegator认证管理器即可
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tulingTokenEnhancer(),jwtAccessTokenConverter()));

        endpoints.
                 // token存储策略:使用jwt存储
                 tokenStore(tokenStore())

                 //授权服务器颁发的token,token增强设置载荷,配置jwt的密钥
                 .tokenEnhancer(tokenEnhancerChain)

                 //用户来获取token的时候需要 进行用户信息检查
                 .userDetailsService(tulingUserDetailService)

                 // 使用密码模式需要传入认证管理器,如果只需授权码模式认证,则不需要注入认证管理器,因为授权码模式用不到用户名密码,密码模式会用到
                 .authenticationManager(authenticationManager)

                 // 刷新token是否可重复使用
                .reuseRefreshTokens(true)

                // 允许获取token的终端支持post和get请求,默认是post的。
                .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
    }

    /**
     * 方法实现说明:授权服务器安全配置
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
     	//允许表单认证
        security.allowFormAuthenticationForClients();
    }
}

2.资源服务器配置类

@Configuration
@EnableResourceServer
public class ResourceServiceConfig extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        // 所有 /user的请求都需要oauth的认证
        http.authorizeRequests()
            .anyRequest()
            .authenticated()
            .and()
            .requestMatchers()
            .antMatchers("/user/**");
    }
}

七.简单测试

  1. 随便定义两个请求: /user下的请求是需要oauth2认证的,/order/id则不需要oauth2认证
@RestController
@RequestMapping("/order")
public class OrderController {

    @GetMapping(value = "/{id}")
    public String getOrder(@PathVariable String id) {
        return "order id : " + id;
    }
}
@RestController
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/getCurrentUser")
    public Object getCurrentUser(Authentication authentication) {
        return authentication.getPrincipal();
    }
}
  1. 直接访问资源服务器管控的资源
  • 失败,提示unauthorized未认证
    在这里插入图片描述
  1. 通过密码模式,获取token
    在这里插入图片描述
    正常生成的token大概就是这样的格式啦,当然我们也可以配置token存储策略用jwt存储,生成jwt类型的token。

{
“access_token”: “7ca4ed69-cb0e-4a34-8031-3aa1d10a2994”,
“token_type”: “bearer”,
“refresh_token”:“c1156ef4-12c4-43ea-a9ac-6dc5d83284e4”,
“expires_in”: 3253,
“scope”:“all”
}

  1. 通过access_token访问资源服务器管控的资源,成功,返回认证信息
    在这里插入图片描述
  2. 直接访问非资源服务器的资源(不需要经过oauth2认证),成功
    在这里插入图片描述

八.小结

  • 好啦,关于OAuth2.0协议介绍,相信小伙伴们有了简单了解了。大家之前如果对接过微信开放平台或者对接过其他的一些服务,应该多少见识过client_id,client_secret,grant_type等等名词,这些就是咱OAuth2.0设计里面的相关授权模式了,OAuth2.0协议应用真的太广泛了,还是得需要了解下的。
  • 万一咱们所做系统之后需要与很多客户端打交道,然后要做认证授权,如果了解OAuth2.0设计思路,对我们自己实现也是有很大帮助的。

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

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

相关文章

数据的表示和存储 第3讲 C语言中的整数

深耕AI ​互联网行业 算法研发工程师 概括 本讲主要介绍了C语言中的整数表示。 无符号整数能够表示的最大值比带符号整数要大。带符号整数使用补码来表示,补码的运算系统是一种模运算系统,能够实现加减运算的统一。在C语言中,如果一个表达式…

利用F.interpolate()函数进行插值操作

函数简介 功能: 利用插值方法,对输入的张量数组进行上\下采样操作,换句话说就是科学合理地改变数组的尺寸大小,尽量保持数据完整。 torch.nn.functional.interpolate(input, sizeNone, scale_factorNone, modenearest, align_c…

【赵渝强老师】K8s的DaemonSets控制器

DaemonSet控制器相当于在节点上启动了一个守护进程。通过使用DaemonSet可以确保一个Pod的副本运行在 Node节点上。如果有新的Node节点加入集群,DaemonSet也会自动给新加入的节点增加一个Pod的副本;反之,当有Node节点从集群中移除时&#xff0…

EdgeRoute_镜像烧录

1. EdgeRouter 概述 EdgeRouter Lite 是由 Ubiquiti Networks 公司生产的一款高性能网络路由器,适用于家庭和小型办公环境。它的尺寸为200 x 90 x 30 mm,重量为345克,配备了双核500 MHz的MIPS64处理器,并带有硬件加速功能&#x…

MySQL_数据类型简介

课 程 推 荐我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈虚 拟 环 境 搭 建 :&#x1…

Vue使用Vue Router路由:开发单页应用

1、路由基础 在单页 Web 应用中,整个项目只有一个 HTML 文件,不同视图(组件的模块)的内容都是在同一个页面中渲染的。当用户切换页面时,页面之前的跳转都是在浏览器端完成的,这时就需要使用前端路由。 路…

APP自动化中 ADB Monkey用法

一、monkey是干什么的? 我们可以使用monkey做手机端性能的压力测试,稳定性测试 二、monkey在使用的时候,他的运行特性 monkey默认配置下执行,会在手机中随机的点击或者轻触我们的手机中应用,不过这个时候&#xff0…

Cortex-M7核心寄存器

参考内容:Cortex-M7编程手册 文章目录 软件执行的处理器模式和权限级别处理器模式软件执行的权限级别 栈Stacks核心寄存器Core registers通用寄存器General-purpose registers链接寄存器Link register程序计数器 Program counter程序状态寄存器Program status regis…

PMP--二模--解题--91-100

文章目录 14.敏捷91、 [单选] 在敏捷团队完成三次迭代之后,项目经理确定团队在这三次迭代中的平均速度是30个故事点。还有292个故事点来完成项目的剩余部分。团队需要多少次额外的迭代才能完成项目? 9.资源管理92、 [单选] 项目经理前往另一个国家执行最…

python yield用法

1 yield关键字 yield在函数中的功能类似于return,不同的是yield每次返回结果之后函数并没有退出,而是 每次遇到yield关键字后返回相应结果,并保留函数当前的运行状态,等待下一次的调用。如果 一个函数需要多次循环执行一个动作&am…

【自动驾驶】控制算法(九)深度解析车辆纵向控制 | 从算法基础到 Carsim 仿真实践

写在前面: 🌟 欢迎光临 清流君 的博客小天地,这里是我分享技术与心得的温馨角落。📝 个人主页:清流君_CSDN博客,期待与您一同探索 移动机器人 领域的无限可能。 🔍 本文系 清流君 原创之作&…

『功能项目』QFrameWorkBug关联Slot(插槽)【67】

我们打开上一篇66QFrameWorkBug拖拽功能的项目, 本章要做的事情是关联插槽Slot 修改脚本:UISlot.cs 修改脚本:UGUICanvas.cs 此时关联Slot已经完成 接下来的文章内容: 1.QFrameWork扔到地上UGUI 2.位置存储功能 3.点击名称寻…

Python可迭代对象(2)

目录 3。字典 字典的构造 字典的添加和修改 字典推导式的使用 以上全部代码编译结果展示 字典复习 4。集合(set) 集合的创建 集合的运算 集合的添加和删除元素 以上全部代码的编译结果 序列解包(Sequence unpacking) 3。字典 字典的构造 #字…

【Linux】nginx连接前端项目

文章目录 一、项目编译1.编译文件2.dist文件 二、Linux nginx配置三、启动nginx 一、项目编译 1.编译文件 2.dist文件 二、Linux nginx配置 在Xshell软件中,点击CtrlAltF进入文件传输找到地址:/usr/local/nginx/html将dist文件传入 找到nginx.conf&…

R包:VennDiagram韦恩图

加载R包 library(VennDiagram)数据 # Prepare character vectors v1 <- c("DKK1", "NPC1", "NAPG", "ERG", "VHL", "BTD", "MALL", "HAUS1") v2 <- c("SMAD4", "DKK1…

【计算机网络 - 基础问题】每日 3 题(十九)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏&…

【Python】curl命令、Api POST导入cURL、python直接使用cURL

文章目录 一、浏览器复制cURL二、API POST直接使用cURL创建接口三、python直接使用cURL构建网络请求四、curl命令详解语法选项实例 cURL是一种命令行工具&#xff0c;常用于通过各种协议&#xff08;如HTTP、HTTPS、FTP等&#xff09;传输数据。它的名字来源于"Client URL…

Python爬虫之requests模块(一)

Python爬虫之requests模块&#xff08;一&#xff09; 学完urllib之后对爬虫应该有一定的了解了&#xff0c;随后就来学习鼎鼎有名的requests模块吧。 一、requests简介。 1、什么是request模块&#xff1f; requests其实就是py原生的一个基于网络请求的模块&#xff0c;模拟…

「漏洞复现」灵当CRM marketing/index.php SQL注入漏洞

0x01 免责声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;作者不为此承担任何责任。工具来自网络&#xff0c;安全性自测&#xff0c;如有侵权请联系删…

python爬虫初体验(一)

文章目录 1. 什么是爬虫&#xff1f;2. 为什么选择 Python&#xff1f;3. 爬虫小案例3.1 安装python3.2 安装依赖3.3 requests请求设置3.4 完整代码 4. 总结 1. 什么是爬虫&#xff1f; 爬虫&#xff08;Web Scraping&#xff09;是一种从网站自动提取数据的技术。简单来说&am…