Oauth2.0 认证

目录

前言

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.mfbz.cn/a/231276.html

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

相关文章

Selenium UI自动化实战过程记录

一.前言 1.1项目框架 项目如何使用框架&#xff1a; 本项目采用unitest框架 设计模式是如何应用&#xff1a;本项目采用pageobject设计模式 UI对象库思想 项目设计 一个模块&#xff08;被测项目的页面&#xff09;对应一个py文件及一个测试类&#xff08;测试文件&#x…

Azure Machine Learning - 使用 Azure OpenAI 服务生成文本

使用 Azure OpenAI 服务生成文本 关注TechLead&#xff0c;分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验&#xff0c;同济本复旦硕&#xff0c;复旦机器人智能实验室成员&#xff0c;阿里云认证的资深架构师&#xff0c;项目管理专业人士&…

快解析结合智邦国际使用教程

北京智邦国际软件技术有限公司&#xff0c;是经中华人民共和国工业和信息化部以及北京经济和信息化委员会评定和审核的双软企业&#xff0c;国家重点支持的高新技术企业。 十几年来致力于企业信息化&#xff0c;主要从事ERP、CRM、项目管理、人资管理、移动应用等企业管理软件的…

探索 SNMPv3 魔法:armbian系统安装snmp服务并通过SNMPV3进行连接控制

文章目录 说明SNMP服务的安装本机连接SNMPV3操作MIB Browser连接SNMPV3问题总结密码过短权限配置错误&#xff0c;导致OID不存在 说明 工具 建议尝试专业版ireasoning MIB brower&#xff0c;因为只有专业版支持SNMP v3的连接。当然&#xff0c;也可以尝试其他SNMP客户端工具 …

C++系列第七篇 数据类型下篇 - 复合类型(结构体、共用体及枚举)

系列文章 C 系列 前篇 为什么学习C 及学习计划-CSDN博客 C 系列 第一篇 开发环境搭建&#xff08;WSL 方向&#xff09;-CSDN博客 C 系列 第二篇 你真的了解C吗&#xff1f;本篇带你走进C的世界-CSDN博客 C 系列 第三篇 C程序的基本结构-CSDN博客 C 系列 第四篇 C 数据类型…

【MATLAB】辛几何模态分解分解+FFT+HHT组合算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 辛几何模态分解&#xff08;CEEMDAN&#xff09;是一种处理非线性和非平稳信号的适应性信号分解方法。通过在信号中加入白噪声&#xff0c;并多次进行经验模态分解&#xff08;EMD&#…

2024年度AI投资策略报告:乘AI之风,破明日之浪

今天分享的AI系列深度研究报告&#xff1a;《2024年度AI投资策略报告&#xff1a;乘AI之风&#xff0c;破明日之浪》。 &#xff08;报告出品方&#xff1a;万联证券&#xff09; 报告共计&#xff1a;25页 1 需求复苏&#xff0c;政策指引热点驱动AI 赋能助推行业发展 1.1 …

uniapp实战 —— 骨架屏

1. 自动生成骨架屏代码 在微信开发者工具中&#xff0c;预览界面点击生成骨架屏 确定后&#xff0c;会自动打开骨架屏代码文件 pages\index\index.skeleton.wxml 2. 将骨架屏代码转换为vue文件 在项目中新建文件 src\pages\index\components\skeleton.vue 将pages\index\index…

湖南大学-电路与电子学-2021期末A卷★(不含解析)

【写在前面】 电路与电子学好像是从2020级开设的课程&#xff0c;故实际上目前只有2020与2021两个年级考过期末考试。 本份卷子的参考性很高&#xff0c;这是2020级的期末考卷。题目都是很典型的&#xff0c;每一道题都值得仔细研究透。 特别注意&#xff1a;看得懂答案跟写得…

代码随想录算法训练营 ---第六十天

今天是最后一天&#xff0c;也是最后一题了&#xff0c;单调栈的应用&#xff0c;是昨天单调栈的变形题。 第一题&#xff1a; 简介&#xff1a; 本题和昨天的接雨水题可以说是很相似的一题。我们知道做单调栈问题&#xff0c;我们要先明确我们的单调栈是递增还是递减。由题意…

Android studio生成二维码

1.遇到的问题 需要生成一个二维码&#xff0c;可以使用zxing第三方组件&#xff0c;增加依赖。 //生成二维码 implementation com.google.zxing:core:3.4.1 2.代码 展示页面 <ImageViewandroid:id"id/qrCodeImageView"android:layout_width"150dp"an…

Kafka集成springboot

安装kafka&#xff0c;直接到官网下载bin文件&#xff0c;本文使用windows进行使用kafka。 下载之后&#xff0c;第一步&#xff0c;启动zookeeper&#xff1a; zookeeper-server-start.bat ..\..\config\zookeeper.properties 第二步&#xff0c;启动kafka&#xff1a; kafka…

玩转系统|利用HestiaCP自建NS解析及邮局并利用MailGun进行发信

前述 HestiaCP是一个VestaCP分叉来的产物&#xff0c;而同样作为VestaCP分叉来的myVesta也具有类似的功能。VestaCP本身作为一个社区的产区&#xff0c;其仅仅有一个商业插件需要每月付费5USD进行使用&#xff0c;因此为了达到完全开放使用的目的&#xff0c;这里选择使用Hest…

yolov8添加cbam注意力机制

(如果添加的是CBAM&#xff0c;已存在&#xff0c;忽略步骤 1 2 3) 步骤1.创建注意力机制-类 ultralytics/nn/modules/conv.py 步骤2.添加到conv.py文件的头文件里 ultralytics/nn/modules/conv.py 步骤3.添加到 init.py文件的头文件里 ultralytics/nn/modules/init.py…

SD之lora训练

目录 为什么要训练自己的模型 SD模型微调方法 准备素材 1 确定要训练的LoRA类型 2 图片收集 3 图片预处理 4 图片标注 安装Koyha_ss 训练lora 1.准备参数和环境 2.启动训练 使用模型 1 拷贝训练过的lora模型 2 启动SD WebUI进行图像生成 为什么要训练自己的模型 …

redis集群(cluster)笔记

1. 定义&#xff1a; 由于数据量过大&#xff0c;单个Master复制集难以承担&#xff0c;因此需要对多个复制集进行集群&#xff0c;形成水平扩展每个复制集只负责存储整个数据集的一部分&#xff0c;这就是Redis的集群&#xff0c;其作用是提供在多个Redis节点间共享数据的程序…

基于Swin_Transformer的图像超分辨率系统

1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义 随着科技的不断发展&#xff0c;图像超分辨率技术在计算机视觉领域中变得越来越重要。图像超分辨率是指通过使用计算机算法将低分辨率图像转换为高分辨率图像的过…

111.am40刷机折腾记4-firefly镜像-dp正常显示

1. 平台&#xff1a; rk3399 am40 4g32g 2. 内核&#xff1a;firefly的内核&#xff08;整体镜像&#xff09; 版本&#xff1a; linux4.4.194 3. 交叉编译工具 &#xff1a;暂时不编译 4. 宿主机&#xff1a;ubuntu18.04 5. 需要的素材和资料&#xff1a;boot-am40-202…

Uos打包工具最新

我司中标的桌面端项目&#xff08;electron开发的应用&#xff09;需兼容统信UOS&#xff0c;关键是要发布到应用商店&#xff0c;首先使用了debreateForUos工具进行打包&#xff0c;打包之后也通过了审核上架到了商店&#xff0c;本以为一切都是如此丝滑顺利&#xff0c;但后续…