.NET 8 Web API 中的身份验证和授权

 本次介绍分为3篇文章: 

1:.Net 8 Web API CRUD 操作
.Net 8 Web API CRUD 操作-CSDN博客

2:在 .Net 8 API 中实现 Entity Framework 的 Code First 方法
https://blog.csdn.net/hefeng_aspnet/article/details/143229912

3:.NET 8 Web API 中的身份验证和授权
https://blog.csdn.net/hefeng_aspnet/article/details/143231987 

参考文章:

1:Dot Net 8 Web API CRUD 操作
https://medium.com/@codewithankitsahu/net-8-web-api-crud-operations-125bb3083113

2:在 .Net 8 API 中实现 Entity Framework 的 Code First 方法
https://medium.com/@codewithankitsahu/implement-entity-framework-a-code-first-approach-in-net-8-api-80b06d219373

3:.NET 8 Web API 中的身份验证和授权
https://medium.com/@codewithankitsahu/authentication-and-authorization-in-net-8-web-api-94dda49516ee

介绍

        在本文中,我们将讨论如何在 .NET 8 Web API 中实现身份验证和授权。这是 .Net 8 系列的延续,所以如果你是新手,请查看我之前的文章。

        身份验证和授权代表着根本不同的功能。在本文中,我们将对这两者进行比较和对比,以展示它们如何以互补的方式保护应用程序。

验证

身份验证就是了解用户的身份。 

例如

Alice 使用她的用户名和密码登录,服务器使用该密码对 Alice 进行身份验证。

授权

授权就是决定是否允许用户采取行动。 

例如

Alice 有权限获取资源,但无权创建资源。

让我们开始在我们的应用程序中实现 Jwt Bearer 令牌。

步骤 1.安装 Microsoft.AspNetCore.Authentication.JwtBearer

安装Microsoft.AspNetCore.Authentication.JwtBearer库以在我们的应用程序中实现 JWT 令牌。 

为了这

  • 前往 ne 获取包管理器。
  • 在浏览选项卡中搜索“Microsoft.AspNetCore.Authentication.JwtBearer”。
  • 选择适当的版本,然后单击“安装”按钮。

步骤2.添加Jwt中间件

在我们的应用中添加 Jwt 中间件。为此,请按照以下步骤操作。 

  • 在 API 解决方案中创建 Helpers 文件夹
  • 添加一个名为“JwtMiddleware”的类
  • 添加JwtMiddleware构造函数并在构造函数中注入RequestDelegate和AppSettings。

//JwtMiddleware.cs
using DotNet8WebAPI.Model;
using Microsoft.Extensions.Options;

namespace DotNet8WebAPI.Helpers
{
    public class JwtMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly AppSettings _appSettings;

        public JwtMiddleware(RequestDelegate next, IOptions<AppSettings> appSettings)
        {
            _next = next;
            _appSettings = appSettings.Value;
        }
    }
}

  • 实现Invoke方法
  • 在invoke方法中,从当前请求中读取授权令牌并转发给attachUserToContext方法进行验证,提取用户信息并附加到当前请求。

//JwtMiddleware.cs
using DotNet8WebAPI.Model;
using DotNet8WebAPI.Services;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Text;

namespace DotNet8WebAPI.Helpers
{
public class JwtMiddleware
{
private readonly RequestDelegate _next;
private readonly AppSettings _appSettings;

public JwtMiddleware(RequestDelegate next, IOptions<AppSettings> appSettings)
{
_next = next;
_appSettings = appSettings.Value;
}

public async Task Invoke(HttpContext context, IUserService userService)
{
var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();

if (token != null)
await attachUserToContext(context, userService, token);

await _next(context);
}

private async Task attachUserToContext(HttpContext context, IUserService userService, string token)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
// set clock skew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
ClockSkew = TimeSpan.Zero
}, out SecurityToken validatedToken);

var jwtToken = (JwtSecurityToken)validatedToken;
var userId = int.Parse(jwtToken.Claims.First(x => x.Type == "id").Value);

//Attach user to context on successful JWT validation
context.Items["User"] = await userService.GetById(userId);
}
catch
{
//Do nothing if JWT validation fails
// user is not attached to context so the request won't have access to secure routes
}
}
}

  • 将我们的“JwtMiddleware”添加到我们的应用程序中
  • 为此,请转到 Program.cs 并添加它。

app.UseMiddleware<JwtMiddleware>();<JwtMiddleware>(); 

步骤 3.实现 UserService 

实现 UserService。我将帮助注册新用户。 

//IUserService.cs
using DotNet8WebAPI.Model;

namespace DotNet8WebAPI.Services
{
public interface IUserService
{
Task<AuthenticateResponse?> Authenticate(AuthenticateRequest model);
Task<IEnumerable<User>> GetAll();
Task<User?> GetById(int id);
Task<User?> AddAndUpdateUser(User userObj);
}

//UserService.cs
using DotNet8WebAPI.Model;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace DotNet8WebAPI.Services
{
public class UserService : IUserService
{
private readonly AppSettings _appSettings;
private readonly OurHeroDbContext db;

public UserService(IOptions<AppSettings> appSettings, OurHeroDbContext _db)
{
_appSettings = appSettings.Value;
db = _db;
}

public async Task<AuthenticateResponse?> Authenticate(AuthenticateRequest model)
{
var user = await db.Users.SingleOrDefaultAsync(x => x.Username == model.Username && x.Password == model.Password);

// return null if user not found
if (user == null) return null;

// authentication successful so generate jwt token
var token = await generateJwtToken(user);

return new AuthenticateResponse(user, token);
}

public async Task<IEnumerable<User>> GetAll()
{
return await db.Users.Where(x => x.isActive == true).ToListAsync();
}

public async Task<User?> GetById(int id)
{
return await db.Users.FirstOrDefaultAsync(x => x.Id == id);
}

public async Task<User?> AddAndUpdateUser(User userObj)
{
bool isSuccess = false;
if (userObj.Id > 0)
{
var obj = await db.Users.FirstOrDefaultAsync(c => c.Id == userObj.Id);
if (obj != null)
{
// obj.Address = userObj.Address;
obj.FirstName = userObj.FirstName;
obj.LastName = userObj.LastName;
db.Users.Update(obj);
isSuccess = await db.SaveChangesAsync() > 0;
}
}
else
{
await db.Users.AddAsync(userObj);
isSuccess = await db.SaveChangesAsync() > 0;
}

return isSuccess ? userObj: null;
}
// helper methods
private async Task<string> generateJwtToken(User user)
{
//Generate token that is valid for 7 days
var tokenHandler = new JwtSecurityTokenHandler();
var token = await Task.Run(() =>
{

var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[] { new Claim("id", user.Id.ToString()) }),
Expires = DateTime.UtcNow.AddDays(7),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
return tokenHandler.CreateToken(tokenDescriptor);
});

return tokenHandler.WriteToken(token);
}
}
}

步骤 4. 添加相应的类模型 

在模型文件夹内添加相应的类模型。

//User.cs
using System.Text.Json.Serialization;

namespace DotNet8WebAPI.Model
{
public class User
{
public int Id { get; set; }
public required string FirstName { get; set; }
public string LastName { get; set; }
public required string Username { get; set; }

[JsonIgnore]
public string Password { get; set; }
public bool isActive { get; set; }
}

//AuthenticateRequest.cs
using System.ComponentModel;

namespace DotNet8WebAPI.Model
{
public class AuthenticateRequest
{
[DefaultValue("System")]
public required string Username { get; set; }

[DefaultValue("System")]
public required string Password { get; set; }
}

//AuthenticateResponse.cs
namespace DotNet8WebAPI.Model
{
public class AuthenticateResponse
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Username { get; set; }
public string Token { get; set; }


public AuthenticateResponse(User user, string token)
{
Id = user.Id;
FirstName = user.FirstName;
LastName = user.LastName;
Username = user.Username;
Token = token;
}
}

//AppSettings.cs
namespace DotNet8WebAPI.Model
{
public class AppSettings
{
public string Secret { get; set; } = string.Empty;
}

步骤 5. 转到 OurHeroDbContext 文件 

转到 OurHeroDbContext 文件并将用户添加为 DBSet。

public DbSet<User> Users { get; set; } 

//OurHeroDbContext.cs
using DotNet8WebAPI.Model;
using Microsoft.EntityFrameworkCore;

namespace DotNet8WebAPI
{
public class OurHeroDbContext : DbContext
{
public OurHeroDbContext(DbContextOptions<OurHeroDbContext> options) : base(options)
{
}

public DbSet<OurHero> OurHeros { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<OurHero>().HasKey(x => x.Id);

modelBuilder.Entity<OurHero>().HasData(
new OurHero
{
Id = 1,
FirstName = "System",
LastName = "",
isActive = true,
}
);

modelBuilder.Entity<User>().HasData(
new User
{
Id = 1,
FirstName = "System",
LastName = "",
Username = "System",
Password = "System",
}
);
}

}

步骤 6.添加 JWT 密钥 

在应用程序设置文件中添加 JWT Secret。

"AppSettings": {
"Secret": "THIS IS USED TO SIGN AND VERIFY JWT TOKENS, REPLACE IT WITH YOUR OWN SECRET, IT CAN BE ANY STRING"
}, 

//appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AppSettings": {
"Secret": "THIS IS USED TO SIGN AND VERIFY JWT TOKENS, REPLACE IT WITH YOUR OWN SECRET, IT CAN BE ANY STRING"
},
"ConnectionStrings": {
"OurHeroConnectionString": "Data Source=LAPTOP-4TSM9SDC;Initial Catalog=OurHeroDB; Integrated Security=true;TrustServerCertificate=True;"
},
"AllowedHosts": "*"

步骤 7.注册 AppSettings 和 UserServices

在应用程序中注册AppSettings和UserServices。

转到 Program.cs 文件并注册我们的服务。

//Program.cs
builder.Services.Configure<AppSettings>(builder.Configuration.GetSection("AppSettings"));
builder.Services.AddScoped<IUserService, UserService>(); 

步骤 8. 运行以下命令

运行以下命令来添加迁移并更新数据库。 

  • 运行add-migration [名称]
  • 更新数据库

步骤 9.实现 AuthorizeAttribute

实现 AuthorizeAttribute 来保护我们并指向匿名用途。 

  • Helpers文件夹中添加AuthorizeAttribute类。
  • 此类与AttributeIAuthorizationFilter 的关联范围。
  • 实现 OnAuthorization 方法。

//AuthorizeAttribute.cs
using DotNet8WebAPI.Model;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;

namespace DotNet8WebAPI.Helpers
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class AuthorizeAttribute : Attribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationFilterContext context)
        {
            var user = (User?)context.HttpContext.Items["User"];
            if (user == null)
            {
                context.Result = new JsonResult(new { message = "Unauthorized" }) { StatusCode = StatusCodes.Status401Unauthorized };
            }
        }
    }
}

步骤 10. 应用 AuthorizeAttribute

根据您的需求,在控制器级别或 Action 方法级别应用AuthorizeAttribute 。 

using DotNet8WebAPI.Helpers;
using DotNet8WebAPI.Model;
using DotNet8WebAPI.Services;
using Microsoft.AspNetCore.Mvc;

namespace DotNet8WebAPI.Controllers
{
    [Route("api/[controller]")]
    [ApiController] // Controller level
    [Authorize]
    public class OurHeroController : ControllerBase
    {
        private readonly IOurHeroService _heroService;
        public OurHeroController(IOurHeroService heroService)
        {
            _heroService = heroService;
        }

        //[ApiController]  // Action method level
        [HttpGet]
        public async Task<IActionResult> Get([FromQuery] bool? isActive = null)
        {
            var heros = await _heroService.GetAllHeros(isActive);
            return Ok(heros);
        }

        [HttpGet("{id}")]
        //[Route("{id}")] // /api/OurHero/:id
        public async Task<IActionResult> Get(int id)
        {
            var hero = await _heroService.GetHerosByID(id);
            if (hero == null)
            {
                return NotFound();
            }
            return Ok(hero);
        }

        [HttpPost]
        public async Task<IActionResult> Post([FromBody] AddUpdateOurHero heroObject)
        {
            var hero = await _heroService.AddOurHero(heroObject);

            if (hero == null)
            {
                return BadRequest();
            }

            return Ok(new
            {
                message = "Super Hero Created Successfully!!!",
                id = hero!.Id
            });
        }

        [HttpPut]
        [Route("{id}")]
        public async Task<IActionResult> Put([FromRoute] int id, [FromBody] AddUpdateOurHero heroObject)
        {
            var hero = await _heroService.UpdateOurHero(id, heroObject);
            if (hero == null)
            {
                return NotFound();
            }

            return Ok(new
            {
                message = "Super Hero Updated Successfully!!!",
                id = hero!.Id
            });
        }

        [HttpDelete]
        [Route("{id}")]
        public async Task<IActionResult> Delete([FromRoute] int id)
        {
            if (!await _heroService.DeleteHerosByID(id))
            {
                return NotFound();
            }

            return Ok(new
            {
                message = "Super Hero Deleted Successfully!!!",
                id = id
            });
        }
    }
}

//UsersController.cs
using DotNet8WebAPI.Helpers;
using DotNet8WebAPI.Model;
using DotNet8WebAPI.Services;
using Microsoft.AspNetCore.Mvc;

namespace DotNet8WebAPI.Controllers
{
    [Route("api/[controller]")] //    /api/Users
    [ApiController]
    public class UsersController : ControllerBase
    {
        private IUserService _userService;

        public UsersController(IUserService userService)
        {
            _userService = userService;
        }

        [HttpPost("authenticate")]
        public async Task<IActionResult> Authenticate(AuthenticateRequest model)
        {
            var response = await _userService.Authenticate(model);

            if (response == null)
                return BadRequest(new { message = "Username or password is incorrect" });

            return Ok(response);
        }

        // POST api/<CustomerController>
        [HttpPost]
        [Authorize]
        public async Task<IActionResult> Post([FromBody] User userObj)
        {
            userObj.Id = 0;
            return Ok(await _userService.AddAndUpdateUser(userObj));
        }

        // PUT api/<CustomerController>/5
        [HttpPut("{id}")]
        [Authorize]
        public async Task<IActionResult> Put(int id, [FromBody] User userObj)
        {
            return Ok(await _userService.AddAndUpdateUser(userObj));
        }
    }
}

步骤11.API安全性

现在我们的 API 对于未经身份验证的用户来说是安全的。 

但是如果您想使用 Swagger 测试我们的 API,那么我们需要接受 Bearer 令牌。

转到 Program.cs 文件并实现它。

builder.Services.AddSwaggerGen(swagger =>Services.AddSwaggerGen(swagger =>
{
    //This is to generate the Default UI of Swagger Documentation
    swagger.SwaggerDoc("v1", new OpenApiInfo
    {
        Version = "v1",
        Title = "JWT Token Authentication API",
        Description = ".NET 8 Web API"
    });
    // To Enable authorization using Swagger (JWT)
    swagger.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
    {
        Name = "Authorization",
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer",
        BearerFormat = "JWT",
        In = ParameterLocation.Header,
        Description = "JWT Authorization header using the Bearer scheme. \r\n\r\n Enter 'Bearer' [space] and then your token in the text input below.\r\n\r\nExample: \"Bearer 12345abcdef\"",
    });
    swagger.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                          new OpenApiSecurityScheme
                            {
                                Reference = new OpenApiReference
                                {
                                    Type = ReferenceType.SecurityScheme,
                                    Id = "Bearer"
                                }
                            },
                            new string[] {}

                    }
                });
});

步骤 12. 运行 Web API 

运行 Web API(按 F5)并调用“/api/Users/authenticate” API。 

步骤 13.复制 JWT 令牌 

  • 单击授权按钮,并在值部分提供令牌“ Bearer <token> ”。
  • 然后点击授权按钮来验证 Web API。

步骤 14. 调用“/api/OurHero” API

现在,如果您调用“/api/OurHero” API,它将起作用,但如果没有 JWT 令牌,它将抛出401(未授权)错误。 

  • 使用 JWT 令牌 — 工作正常。

没有 JWT 令牌 — 抛出401错误。 

概括

        就这样!您已经创建了一个完整的 .NET 8 Web API,用于使用内存数据库和 JWT 身份验证进行 CRUD 操作。您现在可以将此 API 集成到您的前端应用程序中。 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot 与 Vue 共铸卓越采购管理新平台

作者介绍&#xff1a;✌️大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 &#x1f345;获取源码联系方式请查看文末&#x1f345; 推荐订阅精彩专栏 &#x1f447;&#x1f3fb; 避免错过下次更新 Springboot项目精选实战案例 更多项目…

字符串统计(Python)

接收键盘任意录入&#xff0c;分别统计大小写字母、数字及其它字符数量&#xff0c;打印输出。 (笔记模板由python脚本于2024年11月02日 08:23:31创建&#xff0c;本篇笔记适合熟悉python字符串并懂得基本编程技法的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xf…

qt QScrollArea详解

1、概述 QScrollArea是Qt框架中的一个控件&#xff0c;它提供了一个可滚动的视图区域&#xff0c;用于显示超出视图大小的内容。这个控件非常有用&#xff0c;尤其是在处理大型表格、文本区域、图像集合或任何需要滚动浏览的内容时。QScrollArea本身不直接显示内容&#xff0c…

HTML 基础标签——元数据标签 <meta>

文章目录 1. `<meta>` 标签概述2. 属性详解2.1 `charset` 属性2.2 `name` 属性2.3 `content` 属性2.4 `http-equiv` 属性3. 其他常见属性小结在 HTML 文档中,元数据标签 <meta> 是一种重要的标签,用于提供关于文档的信息,这些信息不直接显示在网页内容中,但对于…

InnoDB: corruption in the InnoDB tablespace

磁盘空间满和断电都可能导致mysql无法启动&#xff0c;报错如下&#xff1a; InnoDB: corruption in the InnoDB tablespace. Please refer to InnoDB: http://dev.mysql.com/doc/refman/8.0/en/forcing-innodb-recovery.html InnoDB: about forcing recovery. 20241031 10:54:…

Java网络通信

前言 1. 基本知识 通俗一点就是CS就是要下载应用来访问的&#xff0c;BS是在浏览器上面访问的&#xff0c;不用下载 1.1 IP IP地址就是你电脑的主机号&#xff0c;一台设备都有唯一的IP&#xff0c;端口就是程序的唯一标识 这上面就是我们的ip地址了&#xff0c;有IPv4和…

iptables面试题

1、详述iptales工作流程以及规则过滤顺序&#xff1f; iptables过滤的规则顺序是由上至下&#xff0c;若出现相同的匹配规则则遵循由上至下的顺序 2、iptables的几个表以及每个表对应链的作用&#xff1f; Iptables有四表五链 Filter表 : Filter表是iptables中使用的默认表…

【论文笔记】Attention Prompting on Image for Large Vision-Language Models

&#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为往圣继绝学&#xff0c;为万世开太平。 基本信息 标题: Attention Prompting on I…

【spring】Cookie和Session的设置与获取(@CookieValue()和@SessionAttribute())

&#x1f490;个人主页&#xff1a;初晴~ &#x1f4da;相关专栏&#xff1a;程序猿的春天 获取Cookie 使用 Servlet 获取Cookie&#xff1a; Spring MVC 是基于 Servlet API 构建的原始 Web 框架&#xff0c;也是在 Servlet 的基础上实现的 RestController RequestMapping…

Android启动流程_Init阶段

前言 本文将会介绍 Android 启动流程&#xff0c;将基于 Android 10 代码逻辑介绍原生启动过程。 bootloader 上电 -> 加载 recovery 镜像或者 boot 镜像 -> linux kernel 启动 -> 加载 init 进程 -> 加载 zygote 进程 -> systemserver 进程 -> 系统启动 …

MySQL数据库之存储过程的创建与应用

存储过程 procedure 一.存储过程 作用&#xff1a;将经常使用的功能写成存储过程&#xff0c;方便后续重复使用。 二.创建存储过程 三.调用存储过程 call在计算机中是调用的意思 案例1&#xff1a;查看MySQL用户数 如上图所示&#xff0c;这是查看MySQL数据库中的user个数…

7.使用Redis进行秒杀优化

目录 1. 优化思路 总结之前实现的秒杀过程 下单流程 2. 使用Redis完成秒杀资格判断和库存 0. Redis中数据类型的选用 1.将优惠券信息保存到Redis中 2.基于Lua脚本&#xff0c;判断秒杀库存、一人一单&#xff0c;决定用户是否抢购成功 3. 开启新协程&#xff0c;处理数…

终于把DETR搞懂了!Detection Transformer架构详解及使用方法说明

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

Calling short variants with GATK4

计算生物学实验5: Calling short variants with GATK4 1. 实验目的 本实验目的是利用 GATK4 工具准确高效地检测出基因组中的短变异。通过该工具对样本基因组进行分析&#xff0c;旨在发现单核苷酸变异&#xff08;SNV&#xff09;和小的插入缺失&#xff08;Indel&#xff0…

S32K324 DTCM/DTCM Backdoor使用及测试

文章目录 前言S32K324的Memory mapDTCM的原理DTCM的使用DTCM/DTCM backdoor测试总结 前言 S32K324的Ram在选型手册上给的是512K&#xff0c;但实际上sram只有320k,项目中对ram的需求更大&#xff0c;所以需要拓展一下ram的使用。本文分析DTCM的使用方案及测试结果 S32K324的M…

Pytorch猴痘病识别

Pytorch猴痘病识别 &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 电脑系统&#xff1a;Windows11 显卡型号&#xff1a;NVIDIA Quadro P620 语言环境&#xff1a;python 3.9.7 编译器&#xff1a;jupyte…

网络安全渗透实际案例

目录 案例场景案例目标和工具 案例操作步骤Step 1&#xff1a;信息收集与识别**结果分析** Step 2&#xff1a;漏洞扫描**预期结果** Step 3&#xff1a;漏洞利用与权限验证Step 4&#xff1a;后渗透测试Step 5&#xff1a;报告生成和修复建议**修复建议** 案例总结 下面是一个…

快消零售行业的培训创新:构建在线培训知识库

在快速消费品&#xff08;FMCG&#xff09;行业中&#xff0c;员工的培训和发展对于保持竞争力至关重要。随着电子商务的兴起和消费者行为的变化&#xff0c;快消零售行业需要不断适应新的市场趋势。在线培训知识库作为一种有效的培训工具&#xff0c;可以帮助企业提升员工技能…

软考(中级-软件设计师)计算机网络篇(1101)

第五章&#xff1a;计算机网络基础 **考纲要求**根据开始大纲中相应的考核要求&#xff0c;要求考生掌握一下方面的内容&#xff1a; 1、计算机网络基础知识 网络体系结构传输介质、传输技术、传输方法、传输控制常用网络设备和各类通信设备的特点Client-Server结构、Browser…

【毫米波雷达(四)】车载毫米波雷达下线EOL标定流程

汽车控制器下线EOL标定流程 一、概述二、标定的目的三、雷达标定的要求1、车辆的要求2、标定环境要求四、以软件的角度分析前雷达的EOL标定 一、概述 由于雷达的安装误差会影响雷达对目标位置的检测&#xff0c;导致报警及功能性能下降。因此雷达进行预安装后必须进行角度标定…