第11章 初识IdentityServer4

news2024/9/21 2:36:42

1 构建IdentityServer4 服务

1.1 通过配置类配置类(Config)实例化IdentityServer4中间件

using IdentityServer4.Models;

namespace BuilderServer

{

    /// <summary>

    /// 【配置--类】

    /// <remarks>

    /// 摘要:

    ///    通过该中类的方法成员,对过“IdentityServer4”中间件进行配置设定,并根据这些配置设定。实例化“IdentityServer4”服务。

    /// 说明:

    ///     配置数据最好定义在“appsettings.json”文件中,而非直接嵌入定义在该配置类。

    /// </remarks>

    /// </summary>

    public static class Config

    {

        /// <summary>

        /// 【获取标识资源数组】

        /// <remarks>

        /// 摘要:

        ///    获取认证用户的多个证件单元(Claims:包含:如用户ID、账户、电子邮件地址等)实例,并把这些实例存储到数组实例中,为通过“IdentityServer4”中间件实现身份认证服务提供数据支撑。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///    数组实例,该数组实例中存储着多个证件单元(Claims:包含:如用户ID、账户、电子邮件地址等)实例。

        /// </returns>

        /// </summary>

        public static IEnumerable<IdentityResource> GetIdentityResourceArray()

        {

            return new IdentityResource[]

            {

                new IdentityResources.OpenId(),

                new IdentityResources.Profile(),

            };

        }

        /// <summary>

        /// 【获取作用数组】

        /// <remarks>

        /// 摘要:

        ///    获取序中的Api控制器方法分类实例,并把这些实例存储到数组实例中,为通过“IdentityServer4”中间件实现身份认证服务提供数据支撑。

        /// 应用场景:

        ///     在由于前端版本迭代,而需要更新Api控制器方法时,为了兼容旧的前端就需要“Api版本”控制在不修改旧的Api控制器方法,而是定义新的Api控制器方法,来解决前端版本迭代的兼容性问题。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///    数组实例,该数组实例中存储着Api控制器方法分类的多个实例。

        /// </returns>

        /// </summary>

        public static IEnumerable<ApiScope> GetApiScopeArray()

        {

            return new ApiScope[]

            {

                new ApiScope("api1"),

            };

        }

        /// <summary>

        /// 【获取客户端数组】

        /// <remarks>

        /// 摘要:

        ///    通过“IdentityServer4”中间件,实例化多个客户端实例(客户端通过1个指定的客户端实例获取Token),并把实例存储到数组实例中。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///    数组实例,该数组实例中存储着多个客户端实例(客户端通过1个指定的客户端实例获取Token)。

        /// </returns>

        /// </summary>

        public static IEnumerable<Client> GetClientArray()

        {

            return new Client[]

            {

                //客户端以“client_credentials”方式获取获取Token。

                new Client

                {

                    ClientId = "ClientCredential",

                    ClientName = "客户端凭证认证",

                    //grant_type:ClientCredential

                    //Postman->Body->x-www-form-urlencoded参数:

                    //client_id:ClientCredential

                    //client_secret:511536EF-F270-4058-80CA-1C89C192F69A

                    //grant_type:client_credentials

                    AllowedGrantTypes = GrantTypes.ClientCredentials,

                    ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },

                    AllowedScopes = { "api1" },

                    AccessTokenLifetime = 120 //过期时间=2分钟,默认值:3600秒=1小时。

                },

                 //客户端以“password”方式获取获取Token。

                new Client

                {

                    ClientId = "PasswordClient",

                    ClientName = "客户端密码认证",

                    //grant_type:password

                    //Postman->Body->x-www-form-urlencoded参数:

                    //client_id:PasswordClient

                    //client_secret:511536EF-F270-4058-80CA-1C89C192F69A

                    //grant_type:password

                    //username:zz

                    //password :123456,

                    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,

                    ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },

                    AllowedScopes = { "api1" },

                    AccessTokenLifetime = 120 //过期时间=2分钟,默认值3600秒=1小时。

                },

             };

        }

    }

}

1.2 为“IdentityServer4”服务添加测试性用户

using IdentityModel;

using IdentityServer4.Test;

using IdentityServer4;

using System.Security.Claims;

using System.Text.Json;

namespace BuilderServer

{

    /// <summary>

    /// 【测试用户--类】

    /// <remarks>

    /// 摘要:

    ///    通过该类中的方法成员,获取测试用户类的多个实例,并把实例存储到列表实例中,为测试指定用户通过“IdentityServer4”服务获取Token,测试性的用户。

    /// </remarks>

    /// </summary>

    public class TestUsers

    {

        /// <summary>

        /// 【获取客户列表】

        /// <remarks>

        /// 摘要:

        ///    获取测试用户类的多个实例,并把实例存储到列表实例中,为测试指定用户通过“IdentityServer4”服务获取Token,测试性的用户。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///    列表实例,该列表实例中存储着测试用户类的多个实例。

        /// </returns>

        /// </summary>

        public static List<TestUser> GetUserList()

        {

            var address = new

            {

                street_address = "金水区",

                locality = "郑州",

                postal_code = 69118,//邮编。

                country = "中国"

            };

            //把测试用户类的多个实例存储到列表实例中,为测试指定用户通过“IdentityServer4”服务获取Token,测试性的用户。

            return new List<TestUser>

            {

                new TestUser

                {

                    SubjectId = "1",

                    Username = "zz",

                    Password = "123456",

                    //通过证件单元,构建整个证件。

                    Claims =

                    {

                        new Claim(JwtClaimTypes.Name, "zz"),

                        new Claim(JwtClaimTypes.Email, "zz@email.com"),

                        new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),

                        new Claim(JwtClaimTypes.Address, JsonSerializer.Serialize(address), IdentityServerConstants.ClaimValueTypes.Json)

                    }

                }

            };

        }

    }

}

1.3 重构Program类

//通过配置类中的数据实例,实例化过“IdentityServer4”中间件,最后把过“IdentityServer4”中间件依赖注入到内置容器中,实现当前程序据这些配置设定,实例化“IdentityServer4”服务。

builder.Services.AddIdentityServer()

               .AddTestUsers(TestUsers.GetUserList())//“IdentityServer4”服务添加测试性用户。

               .AddInMemoryIdentityResources(Config.GetIdentityResourceArray()) // “IdentityServer4”服务添加测试性用户。

               .AddInMemoryApiScopes(Config.GetApiScopeArray())//指定客户端所调用Api控件器方法的作用域(版本)

               .AddInMemoryClients(Config.GetClientArray())//1个指定的客户端实例获取Token的认证方式。

               .AddDeveloperSigningCredential();//临时生成的证书证书。

var app = builder.Build();

// “IdentityServer4”管道中间件集成到.Net7框架内置管道中,以实现前程序对“IdentityServer4”服务的支持。

app.UseIdentityServer();

// Configure the HTTP request pipeline.

if (app.Environment.IsDevelopment())

{

    app.UseSwagger();

    app.UseSwaggerUI();

}

app.UseHttpsRedirection();

app.UseAuthorization();

//把内置授权管道中间件集成到.Net7框架内置管道中。

//注意:

//内置授权管道中间件必须集成在“IdentityServer4”服务程序中,否则在使用Postman调试经过认证特性标记的Api控制器方法时会出现:“401Unauthorized”错误。

app.UseAuthentication();

1.4 通过Postman测试IdentityServer4服务

 

2 通过“IdentityServer4.AccessTokenValidation”中间件获取IdentityServer4服务所发送的“JwtBearer”令牌(Token)实例

2.1 TestController控制器

using IdentityModel.Client;

using Microsoft.AspNetCore.Authorization;

using Microsoft.AspNetCore.Mvc;

namespace AccessToken.Controllers

{

    /// <summary>

    /// 【登录管Api控制器--类--无认证特性标记】

    /// </summary>

    /// <remarks>

    /// 摘要:

    ///     通过该类中的方法成员,用于对IdentityServer4服务验证。

    /// </remarks>

    [Route("api/[controller]")]

    [ApiController]

    public class TestController : ControllerBase

    {

        /// <summary>

        /// 【Swagger登录--无认证特性标记】

        /// </summary>

        /// <remarks>

        /// 摘要:

        ///     获取通过IdentityServer4服务所发送的“JwtBearer”令牌(Token)实例的字符串值。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///    令牌(Token)实例的字符串值。

        /// </returns>

        [HttpGet("GetToken")]

        public async Task<string> GetToken()

        {

            //获取IdentityServer4服务中的客户端实例。

            var client = new HttpClient();

            var config = new DiscoveryDocumentRequest()

            {

                Address = "https://localhost:44360/",

                Policy = new DiscoveryPolicy() { RequireHttps = false }

            };  //忽略IP或域名时Https请求

            var disco = await client.GetDiscoveryDocumentAsync(config);

            //根据IdentityServer4服务中的客户端实例,获取“JwtBearer”令牌(Token)实例。

            var tokenResponse = await client.RequestClientCredentialsTokenAsync(

                new ClientCredentialsTokenRequest

                {

                    Address = disco.TokenEndpoint,

                    ClientId = "ClientCredential",

                    ClientSecret = "511536EF-F270-4058-80CA-1C89C192F69A",

                    Scope = "api1",

                });

            if (tokenResponse.IsError)

            {

                return tokenResponse.Error;

            }

            //返回“JwtBearer”令牌(Token)实例的字符串值。

            return tokenResponse.AccessToken;

        }

        /// <summary>

        /// 【Swagger登录--有认证特性标记】

        /// </summary>

        /// <remarks>

        /// 摘要:

        ///    在通过IdentityServer4服务所发送的“JwtBearer”令牌(Token)实例认证并授权后,获取当前Api方法的实例值。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///    当前Api方法的实例值。

        /// </returns>

        [Authorize("api1")]

        [HttpGet("GetValue")]

        public IEnumerable<string> GetValue()

        {

            return new string[] { "value1", "value2" };

        }

    }

}

2.2 重构Program类

using Microsoft.IdentityModel.Tokens;

using Microsoft.OpenApi.Models;

using System.Reflection;

using System.Text;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle

builder.Services.AddEndpointsApiExplorer();

//通过“IdentityServer4.AccessTokenValidation”中间件,把“JwtBearer”中间件注入.Net7框架内置容器中,

builder.Services.AddAuthentication("Bearer")

    .AddIdentityServerAuthentication(options =>

    {

        options.Authority = "https://localhost:44360/";//鉴权(认证)服务地址

        options.RequireHttpsMetadata = false;

        //缓冲过期时间,“JwtBearer”令牌(Token)的总有效时间等于该时间加上jwt的过期时间,缓冲过期时间的默认值为“5分钟

        //当前把缓冲过期时间设定为:0,指定令牌(Token)的总有效时间即为jwt的过期时间。

        //注意:

        //如果不设定“JwtBearer”缓冲过期时间设定为:0,即在IdentityServer4服务中的时间(120秒之后)过期后,经过认证特性标记的Api控制器方法依然可以获取其值,因为还“5分钟的缓冲过期。

        options.JwtValidationClockSkew = TimeSpan.FromSeconds(0);

    });

//通过.Net7框架内置认证中间件,把"api1"策略注入.Net7框架内置容器中,

builder.Services.AddAuthorization(option =>

{

    option.AddPolicy("Api1", builder =>

    {

        builder.RequireAuthenticatedUser();

        builder.RequireClaim("scope", "api1");

    });

});

//通过AddSwaggerGen依赖注入中间,获取Api控制器方法的版本控制信息和注释等数据信息,依赖注入.Net7框架的内置容器中,为在“index.html”页面上渲染显示这些信息,作好预处理操作。

builder.Services.AddSwaggerGen(options =>

{

    options.SwaggerDoc("v1", new OpenApiInfo { Title = "IdentityServer4.AccessTokenValidation", Version = "v1" });

    //获取"AccessToken.xml"文件的文件名。

    string _xmlFileName = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";

    //获取"SecondPracticeServer.xml"文件的绝对路径。

    string _xmlFilePath = Path.Combine(AppContext.BaseDirectory, _xmlFileName);

    //把控件器行为方法中的注释信息加载到"Swagger/index.html"页面中的控件器行为方法进行渲染显示。

    options.IncludeXmlComments(_xmlFilePath, true);

});

var app = builder.Build();

app.UseSwagger();

app.UseSwaggerUI();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

2.3 通过Postman验证“IdentityServer4”服务及其授权

2.3.1 先通过Postman获取“JwtBearer”令牌(Token)

2.3.2 通过Headers授权认证特性标记的Api控制器方法

2.3.3通过Authorization授权认证特性标记的Api控制器方法

 3 通过“IdentityModel”中间件获取IdentityServer4服务所发送的“JwtBearer”令牌(Token)实例

    1、通过Nuget引用:IdentityModel包。

    2、通过Nuget引用:Microsoft.AspNetCore.Authentication.JwtBearer包。

3.1 重构Program类

//通过“Microsoft.AspNetCore.Authentication.JwtBearer”中间件,把“JwtBearer”中间件注入.Net7框架内置容器中,

builder.Services.AddAuthentication("Bearer")

    .AddJwtBearer("Bearer", options =>

    {

        options.Authority = "https://localhost:44360/";

        options.RequireHttpsMetadata = false;

        options.TokenValidationParameters = new TokenValidationParameters

        {

            //指示是否对指定令牌(Token)的过期时间进行限定,当前设定为:true,即限定。

            RequireExpirationTime = true,

            //指示是否对指定令牌(Token)的生命周期进行自动管理,当前设定为:true,即管理,

            //当前指定令牌(Token)的生命周期结束时,程序必须重新生成1个新的指定令牌(Token)才能方法授权页面。

            //使用当前时间与TokenClaims中的NotBeforeExpires对比后,进行管理。

            ValidateLifetime = true,

            //缓冲过期时间,“JwtBearer”令牌(Token)的总有效时间等于该时间加上jwt的过期时间,缓冲过期时间的默认值为“5分钟

            //当前把缓冲过期时间设定为:0,指定令牌(Token)的总有效时间即为jwt的过期时间。

            //注意:

            //如果不设定“JwtBearer”缓冲过期时间设定为:0,即在IdentityServer4服务中的时间(120秒之后)过期后,经过认证特性标记的Api控制器方法依然可以获取其值,因为还“5分钟的缓冲过期。

            ClockSkew = TimeSpan.FromSeconds(0),

        };

    });

//通过.Net7框架内置认证中间件,把"api1"策略注入.Net7框架内置容器中,

builder.Services.AddAuthorization(option =>

{

    option.AddPolicy("Api1", builder =>

    {

        builder.RequireAuthenticatedUser();

        builder.RequireClaim("scope", "api1");

    });

});

//通过AddSwaggerGen依赖注入中间,获取Api控制器方法的版本控制信息和注释等数据信息,依赖注入.Net7框架的内置容器中,为在“index.html”页面上渲染显示这些信息,作好预处理操作。

builder.Services.AddSwaggerGen(options =>

{

    options.SwaggerDoc("v1", new OpenApiInfo { Title = "IdentityServer4.AccessTokenValidation", Version = "v1" });

    //获取"AccessToken.xml"文件的文件名。

    string _xmlFileName = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";

    //获取"SecondPracticeServer.xml"文件的绝对路径。

    string _xmlFilePath = Path.Combine(AppContext.BaseDirectory, _xmlFileName);

    //把控件器行为方法中的注释信息加载到"Swagger/index.html"页面中的控件器行为方法进行渲染显示。

    options.IncludeXmlComments(_xmlFilePath, true);

});

3.2 通过Postman验证“IdentityServer4”服务及其授权

    同上

4 注意:

4.1 启动

    把所有项目的启动方式修改为:“IIS Express

4.2 设定“JwtBearer”令牌(Token)缓冲过期时间为:0

4.2.1 通过“IdentityServer4.AccessTokenValidation”中间件设定

//通过“IdentityServer4.AccessTokenValidation”中间件,把“JwtBearer”中间件注入.Net7框架内置容器中,

builder.Services.AddAuthentication("Bearer")

    .AddIdentityServerAuthentication(options =>

    {

        options.Authority = "https://localhost:44360/";//鉴权(认证)服务地址

        options.RequireHttpsMetadata = false;

        //缓冲过期时间,“JwtBearer”令牌(Token)的总有效时间等于该时间加上jwt的过期时间,缓冲过期时间的默认值为“5分钟”,

        //当前把缓冲过期时间设定为:0,指定令牌(Token)的总有效时间即为jwt的过期时间。

        //注意:

        //如果不设定“JwtBearer”缓冲过期时间设定为:0,即在IdentityServer4服务中的时间(120秒之后)过期后,经过认证特性标记的Api控制器方法依然可以获取其值,因为还“5分钟”的缓冲过期。

        options.JwtValidationClockSkew = TimeSpan.FromSeconds(0);

    });

4.2.2 通过“Microsoft.AspNetCore.Authentication.JwtBearer”中间件设定

//通过“Microsoft.AspNetCore.Authentication.JwtBearer”中间件,把“JwtBearer”中间件注入.Net7框架内置容器中,

builder.Services.AddAuthentication("Bearer")

    .AddJwtBearer("Bearer", options =>

    {

        options.Authority = "https://localhost:44360/";

        options.RequireHttpsMetadata = false;

        options.TokenValidationParameters = new TokenValidationParameters

        {

            //指示是否对指定令牌(Token)的过期时间进行限定,当前设定为:true,即限定。

            RequireExpirationTime = true,

            //指示是否对指定令牌(Token)的生命周期进行自动管理,当前设定为:true,即管理,

            //当前指定令牌(Token)的生命周期结束时,程序必须重新生成1个新的指定令牌(Token)才能方法授权页面。

            //使用当前时间与Token的Claims中的NotBefore和Expires对比后,进行管理。

            ValidateLifetime = true,

            //缓冲过期时间,“JwtBearer”令牌(Token)的总有效时间等于该时间加上jwt的过期时间,缓冲过期时间的默认值为“5分钟”,

            //当前把缓冲过期时间设定为:0,指定令牌(Token)的总有效时间即为jwt的过期时间。

            //注意:

            //如果不设定“JwtBearer”缓冲过期时间设定为:0,即在IdentityServer4服务中的时间(120秒之后)过期后,经过认证特性标记的Api控制器方法依然可以获取其值,因为还“5分钟”的缓冲过期。

            ClockSkew = TimeSpan.FromSeconds(0),

        };

    });

4.3 内置授权管道中间件必须集成在“IdentityServer4”服务程序中

    内置授权管道中间件必须集成在“IdentityServer4”服务项目中,否则在使用Postman调试经过认证特性标记的Api控制器方法时会出现:“401Unauthorized”错误,如下图所示。

 

对以上功能更为具体实现和注释见:221204_10IdentityServer4(初识IdentityServer4)。

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

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

相关文章

如何给firefox和google chrome鼠标手势

背景 已经习惯了有鼠标手势&#xff0c;因为一天到晚都在浏览器上查询资料&#xff0c;所以必须把这个鼠标手势设置好。 firefox 搜索Foxy Gestures然后安装 google chrome crxMouse Chrome 点击google浏览器上的扩展程序图标&#xff0c;然后点击管理扩展程序&#xff1a…

游泳耳机哪个牌子好、分享几款游泳听音乐最好的耳机推荐

如今,水上运动爱好者越来越多了,无论是游泳,还是冲浪早已成为了我们很多人经常参加的运动项目。不过他们都抱怨过类似的问题——可以在水上运动中使用的无线耳机实在是太少了。防水性能达不到可游泳级别,不带内存需要配备手机使用,这些都是造成耳机无法在水上使用的原因。今天小…

【matplotlib】1-使用函数绘制图表

文章目录使用函数绘制图表1.绘制matplotlib图表组成元素的主要函数2.准备数据3.函数用法3.1函数plot()--展现变量的趋势变化3.2函数scatter()--寻找变量之间的关系3.3函数xlim()--设置x轴的数值显示范围3.4函数xlabel()--设置x轴的标签文本3.5 函数grid()--绘制刻度线的网格线3…

Kong(三)Konga UI安装和使用

一 konga 的github地址 konga安装参考 ① Kong 可视化UI 选择 官方kong-dashboard 1&#xff09;收费&#xff1a;当前kong的社区版是没有dashboard的,但是付费的企业版是有带的2&#xff09;kong-dashboard最新版本v3.6.0,只支持到kongv0.14.x,对于更高的kong版本,功能支…

SpringBoot整合RabbitMQ,实现单机抢票系统

MQ全称为Message Queue, 消息队列&#xff08;MQ&#xff09;是一种应用程序对应用程序的通信方法。MQ是消费-生产者模型的一个典型的代表&#xff0c;一端往消息队列中不断写入消息&#xff0c;而另一端则可以读取队列中的消息。 消息中间件最主要的作用是解耦&#xff0c;中间…

C与C++中的常用符号与标点用法详解及实例

C与C中的常用符号与标点符号有&#xff1a;“”、“-”、“*”、 “/”、“%”、“&”、“\”、“|”、“~”、“^”、“&”、“|”、“&#xff01;”、“>”、“<”、""、“#”、“&#xff1f;”、“&#xff0c;”、“.”、“&#xff1a;”、单引…

d3rlpy离线强化学习算法库安装及使用

GitHub - takuseno/d3rlpy: An offline deep reinforcement learning library d3rlpy&#xff0c;离线强化学习算法库 我装在windows下用anaconda&#xff0c;按照官网教程 conda install -c conda-forge d3rlpy 第一次安装报错CondaSSLError: OpenSSL appears to be unavaila…

Kubernetes的service详解

文章目录Service介绍Service类型Service使用ClusterIP类型的ServiceHeadLiness类型的ServiceNodePort类型的ServiceLoadBalancer类型的ServiceExternalName类型的ServiceIngress介绍Service介绍 在kubernetes中&#xff0c;pod是应用程序的载体&#xff0c;我们可以通过pod的i…

程序人生 | 与足球共舞的火柴人(致敬格拉利什,赋予足球更深的意义)

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;也会涉及到服务端 &#x1f4c3;个人状态&#xff1a; 在校大学生一枚&#xff0c;已拿多个前端 offer&#xff08;秋招&#xff09; &#x1f680;未…

从0开始学游戏开发

对于开发而言&#xff0c;了解一下如何从零开始做游戏是一个非常有趣且有益的过程(并不)。这里我先以大家对游戏开发一无所知作为前提&#xff0c;以一个简单的游戏开发作为.从0开始学游戏开发。 写在最前面 对于开发而言&#xff0c;了解一下如何从零开始做游戏是一个非常有趣…

Twice-JavaSE01

狂神学习路线&#xff1a; 今天又重头开始复习Java了&#xff0c;不顾一切往前冲吧。 空常量null不能直接输出。其他几种基本数据类型可以直接输出。 定义变量时要给赋值才行&#xff0c;浮点型默认为double,float类型后要加f. 注意&#xff1a;byte和short不能直接跟char做…

【强化学习论文合集 | 2019年合集】一. ICML-2019 强化学习论文

强化学习(Reinforcement Learning, RL),又称再励学习、评价学习或增强学习,是机器学习的范式和方法论之一,用于描述和解决智能体(agent)在与环境的交互过程中通过学习策略以达成回报最大化或实现特定目标的问题。 本专栏整理了近几年国际顶级会议中,涉及强化学习(Rein…

C++-容器:string使用介绍(非常全面,详细)

string的初始化 1.常见初始化方式 string对象的初始化和普通类型变量的初始化基本相同&#xff0c;只是string作为类&#xff0c;还有类的一些特性&#xff1a;使用构造函数初始化。如下表&#xff0c;第2 4 6条是作为类才有的初始化方式&#xff1a; 当然&#xff0c;也可以…

MySQL数据库之事务

MySQL数据库之事务一、事务的概念二、事务的ACID特点2.1 原子性&#xff08;保证事务的整体性&#xff09;2.2 一致性&#xff08;保证数据的完整性&#xff09;2.3 隔离性2.4 持久性三、事务控制语句3.1 测试begin和commit&#xff08;开始事务和提交事务&#xff09;begin开启…

毕业设计-基于机器视觉的车型识别系统

目录 前言 课题背景和意义 实现技术思路 实现效果图样例 前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科…

【人脸识别】Octuplet Loss:一个可以提高低分辨率和跨分辨率人脸识别效果的损失

论文题目&#xff1a;《Octuplet Loss:Make Face Recognition Robust to Image Resolution》 论文地址&#xff1a;https://arxiv.org/pdf/2207.06726v1.pdf 代码地址&#xff1a;https://github.com/martlgap/octuplet-loss 1.概述 一般来说&#xff0c;在图像分辨率方面&…

多线程设计模式-全面详解(学习总结---从入门到深化)

目录 Single Thread Execution 设计模式 机场过安检 非线程安全 问题分析 首字母相同却未通过检查 为何出现首字母不相同的情况 线程安全 Future 设计模 Master-Worker 设计模式 生产者消费者设计模式 Immutable 不可变对象设计模式 关于时间日期 API 线程不安全的问题…

Attention机制详解(深入浅出)

目录1. 为什么要有Attention2. Attention机制我们都知道&#xff0c;对于人类来说注意力是非常重要的一件事。有了注意的能力我们才能在一个比较复杂的环境中&#xff0c; 把有限的注意力放到重要的地方。在这一节中&#xff0c;我们将了解如何使得我们的网络也具有产生注意力的…

47. 全排列 II

关上过去和未来的铁门&#xff0c;活在“今天”这个舱室中。 ——《人性的优点》 47. 全排列 II 给定一个可包含重复数字的序列 nums &#xff0c;按任意顺序 返回所有不重复的全排列。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,2] 输…

蓝桥杯嵌入式AT24C02

文章目录前言一、AT24C02原理图二、IIC通信协议三、代码编写1.拷贝官方驱动程序2.编写AT24C02读写函数1.查看AT24C02芯片手册确定AT24C02器件地址2.读函数编写3.写函数编写4.代码使用总结前言 本文将带大家了解IIC协议&#xff0c;并带大家编写AT24C02的驱动代码。 一、AT24C…