【.NET框架实战】IdentityServer4身份验证、授权

什么是身份认证

身份认证是指当客户端访问服务端资源时,验证客户端是否合法的一种机制

什么是授权

授权就是指当客户端经过身份认证后,能够有限的访问服务端资源的一种机制

为什么要使用身份验证和授权

为了保证服务端资源的安全,我们要理解必须从真实项目中去理解

身份认证和授权方式有哪些

​ 1、Base认证

​ Base64编号认证 == https

​ 2、Digest认证

​ MD5消息摘要认证 == https

​ 3、Bearer认证

​ 就是基于token(电子身份证)认证,讲用户信息等其他信息转换成为token,然后以token进行认证

​ token认证是一种无状态的认证方式,能够无限扩展,特别适合做单点登录

​ 3.1 OAuth 2.0 ==== 授权方式的认证

​ 3.2 JWT的也是一种身份认证

​ token 分两种类型

​ 引用类型token == OAuth 2.0

​ 无用户相关信息

​ 自包含token

​ 有用户相关信息 JWT === 地址,电话,id,等

​ 在实际分布式项目中,大部分都是使用Bearer来进行身份认证和身份授权

​ 在分布式项目或者微服务项目中,为了保证系统统一登录(SSO登录),

​ 使用OpenID协议标准来规范身份认证功能 === 规范

​ 同时使用OAuth 2.0协议标准来规范权限访问 === 规范

​ 为了将身份认证(单点登录)和授权结合起来,所以出现了OpenID Connect协议标准 === 接口

​ OpenID Connect = OpenID + OAuth 2.0

​ SSO+OAuth 2.0可以实现单点登录和授权

​ IdentityServer4 也可以实现单点登录和授权

​ 然后综合实现了这些框架就是今天要讲的IdentityServer4 身份认证服务器

如何在项目中使用IdentityServer4

IdentityServer4 是什么

​ IdentityServer是基于OpenID Connect协议标准的身份认证和授权程序,它实现了OpenID Connect 和 OAuth 2.0 协议。

IdentityServer4 功能

保护你的资源
使用本地帐户或通过外部身份提供程序对用户进行身份验证
提供会话管理和单点登录
管理和验证客户机
向客户发出标识和访问令牌
验证令牌

IdentityServer4 内部概念

下面对以下几个转用术语进行解释

用户(User)
用户是使用已注册的客户端(指在id4中已经注册)访问资源的人。

客户端(Client)

客户端就是从identityserver请求令牌的软件(你可以理解为一个app即可),既可以通过身份认证令牌来验证识别用户身份,又可以通过授权令牌来访问服务端的资源。但是客户端首先必须在申请令牌前已经在identityserver服务中注册过。

实际客户端不仅可以是Web应用程序,app或桌面应用程序(你就理解为pc端的软件即可),SPA,服务器进程等。

资源(Resources)

资源就是你想用identityserver保护的东东,可以是用户的身份数据或者api资源。
每一个资源都有一个唯一的名称,客户端使用这个唯一的名称来确定想访问哪一个资源(在访问之前,实际identityserver服务端已经配置好了哪个客户端可以访问哪个资源,所以你不必理解为客户端只要指定名称他们就可以随便访问任何一个资源)。

用户的身份信息实际由一组claim组成,例如姓名或者邮件都会包含在身份信息中(将来通过identityserver校验后都会返回给被调用的客户端)。

API资源就是客户端想要调用的功能(通常以json或xml的格式返回给客户端,例如webapi,wcf,webservice),通常通过webapi来建立模型,但是不一定是webapi,我刚才已经强调可以使其他类型的格式,这个要看具体的使用场景了。

身份令牌(顾名思义用于做身份认证,例如sso其实主要就是用于身份认证) id_token jwt
一个身份令牌指的就是对认证过程的描述。它至少要标识某个用户(Called the sub aka subject claim)的主身份信息,和该用户的认证时间和认证方式。但是身份令牌可以包含额外的身份数据,具体开发者可以自行设定,但是一般情况为了确保数据传输的效率,开发者一般不做过多额外的设置,大家也可以根据使用场景自行决定。

访问令牌(用于做客户端访问授权) access_token oauth 2.0
访问令牌允许客户端访问某个 API 资源。客户端请求到访问令牌,然后使用这个令牌来访问 API资源。访问令牌包含了客户端和用户(如果有的话,这取决于业务是否需要,但通常不必要)的相关信息,API通过这些令牌信息来授予客户端的数据访问权限。

IdentityServer4 角色逻辑关系图

微服务中使用IdentityServer4

IdentityServer4 官网地址

中文地址:http://www.identityserver.com.cn/Home/Detail/Zhengtizongshu

英文地址:https://identityserver4.readthedocs.io/en/3.1.0/

客户端认证模式

条件

1、IdentityServer4 授权服务器(IdentityServer)

2、客户端(Client)

3、微服务系统(Resources)

4、用户

步骤

1、NutGet下载IdentityServer4 在资源服务器中

1.1、在IOC容器中配置IdentityServer4

 // 1、ioc容器中添加IdentityServer4services.AddIdentityServer().AddDeveloperSigningCredential()// 1、用户登录配置.AddInMemoryApiResources(Config.GetApiResources()) // 2、存储Api资源.AddInMemoryClients(Config.GetClients()) // 3、存储客户端(模式)

1.2、使用IdentityServer4

// 1、使用IdentityServe4app.UseIdentityServer();    //2、添加静态资源访问app.UseStaticFiles();

1.3、配置测试用户Config类

   /// <summary>/// 1、Identity测试使用/// </summary>public class Config{/// <summary>/// 1、微服务API资源/// </summary>/// <returns></returns>public static IEnumerable<ApiResource> GetApiResources(){return new List<ApiResource>{new ApiResource("TeamService", "TeamService api需要被保护")};}/// <summary>/// 2、客户端/// </summary>/// <returns></returns>public static IEnumerable<Client> GetClients(){return new List<Client>{new Client{ClientId = "client",// 没有交互性用户,使用 clientid/secret 实现认证。AllowedGrantTypes = GrantTypes.ClientCredentials,// 用于认证的密码ClientSecrets ={new Secret("secret".Sha256())},// 客户端有权访问的范围(Scopes)AllowedScopes = { "TeamService" }}};}
}

​ 2、微服务配置

​ 2.1 Nuget下载IdentityServer4.AccessTokenValidation

​ 2.2 配置身份和授权认证(配置认证资源,让资源服务器进行保护)

 // 6、校验AccessToken,从身份校验中心进行校验services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme).AddIdentityServerAuthentication(options => {options.Authority = "http://localhost:5005"; // 1、授权中心地址options.ApiName = "TeamService"; // 2、api名称(项目具体名称)options.RequireHttpsMetadata = false; // 3、https元数据,不需要});

​ 2.3 开启身份认证

app.UseAuthentication(); // 1、使用身份验证

​ 3、客户端配置

​ 3.1 Nuget下载IdentityModel

​ 3.2 调用代码即可

​ 以上默认客户端认证模式

客户端密码认证模式

条件

1、用户Test

步骤

1、在Config中添加新客户端

new Client
{ClientId = "client-password",// 使用用户名密码交互式验证AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,// 用于认证的密码ClientSecrets ={new Secret("secret".Sha256())},// 客户端有权访问的范围(Scopes)AllowedScopes = { "TeamService" }
},

2、在config中添加test用户

/// <summary>/// 客户端下面的用户/// </summary>/// <returns></returns>public static List<TestUser> GetUsers(){return new List<TestUser>(){new TestUser{SubjectId="1",Username="tony",Password="123456"}};}

3、在startup中添加配置

 // 1、ioc容器中添加IdentityServer4services.AddIdentityServer().AddDeveloperSigningCredential()// 1、用户登录配置.AddInMemoryApiResources(Config.GetApiResources()) // 2、存储Api资源.AddInMemoryClients(Config.GetClients()) // 3、存储客户端(模式).AddTestUsers(Config.GetUsers())// 4、添加登录用户(模式)

4、 开始调用

​ 在代码中已经写好调用过程

授权码模式认证(通过code获取assess_token)

条件

1、OpenIdConnect

步骤

1、Nuget下载Microsoft.AspNetCore.Authentication.OpenIdConnect

2、认证服务器配置

​ 2.1 在config中添加openid身份资源声明

public static IEnumerable<IdentityResource> Ids => new List<IdentityResource>{new IdentityResources.OpenId(),new IdentityResources.Profile()};

​ 2.2 在config中添加客户端

// openid客户端
new Client
{
ClientId="client-code",
ClientSecrets={new Secret("secret".Sha256())},
AllowedGrantTypes=GrantTypes.Code,
RequireConsent=false,
RequirePkce=true,RedirectUris={ "https://localhost:5006/signin-oidc"},PostLogoutRedirectUris={ "https://localhost:5006/signout-callback-oidc"},AllowedScopes=new List<string>{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"TeamService" // 启用对刷新令牌的支持
},// 增加授权访问
AllowOfflineAccess=true
}

​ 2.3 添加openidtest用户

 // openid 身份验证new TestUser{SubjectId = "818727", Username = "张三", Password = "123456",Claims ={new Claim(JwtClaimTypes.Name, "张三"),new Claim(JwtClaimTypes.GivenName, "三"),new Claim(JwtClaimTypes.FamilyName, "张"),new Claim(JwtClaimTypes.Email, "zhangsan@email.com"),new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),new Claim(JwtClaimTypes.WebSite, "http://zhangsan.com"),//  new Claim(JwtClaimTypes.Address, @"{ '城市': '杭州', '邮政编码': '310000' }", IdentityServer4.IdentityServerConstants.ClaimValueTypes.Json)}}

​ 2.4、在startup中添加配置

 // 1、ioc容器中添加IdentityServer4services.AddIdentityServer().AddDeveloperSigningCredential()// 1、用户登录配置.AddInMemoryApiResources(Config.GetApiResources()) // 2、存储Api资源.AddInMemoryClients(Config.GetClients()) // 3、存储客户端(模式).AddTestUsers(Config.GetUsers())// 4、添加登录用户(模式).AddInMemoryIdentityResources(Config.Ids); // 4、使用openid模式

​ 2.5 准备登陆ui页面

​ 代码中已经准备好

3、客户端配置

​ 3.1 startup.cs文件中配置

            // 1、添加身份验证// 我们使用cookie来本地登录用户(通过“Cookies”作为DefaultScheme),并且将DefaultChallengeScheme设置为oidc。因为当我们需要用户登录时,我们将使用OpenID Connect协议。services.AddAuthentication(options =>{options.DefaultScheme = "Cookies";options.DefaultChallengeScheme = "oidc";})// 添加可以处理cookie的处理程序.AddCookie("Cookies")// 用于配置执行OpenID Connect协议的处理程序.AddOpenIdConnect("oidc", options =>{options.Authority = "http://localhost:5005";    // 受信任令牌服务地址options.RequireHttpsMetadata = false;options.ClientId = "client-code";options.ClientSecret = "secret";options.ResponseType = "code";options.SaveTokens = true;  // 用于将来自IdentityServer的令牌保留在cookie中// 1、添加授权访问api的支持options.Scope.Add("TeamService");options.Scope.Add("offline_access");});

​ 3.2 使用配置

 // 1、使用静态页面app.UseStaticFiles();// 2、开启身份验证app.UseAuthentication();

IdentityServer4持久化

主要是将资源数据,用户数据,身份数据全部进行放在数据库进行存储。

条件

1、ConfigurationDbContext

​ 用于配置数据,如clients,resources和scopes。

2、PersistedGrantDbContext

​ 用于临时操作数据,如授权代码和刷新令牌

步骤

1、Nuge安装IdentityServer4.EntityFramework

​ Microsoft.EntityFrameworkCore.SqlServer

​ Microsoft.EntityFrameworkCore.Tools

2、重新配置Startup.cs文件

// 2、资源客户端持久化操作var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;var connectionString = Configuration.GetConnectionString("DefaultConnection");services.AddIdentityServer().AddConfigurationStore(options =>{options.ConfigureDbContext = builder =>{builder.UseSqlServer(connectionString, options =>options.MigrationsAssembly(migrationsAssembly));};}).AddOperationalStore(options =>{options.ConfigureDbContext = builder =>{builder.UseSqlServer(connectionString, options =>options.MigrationsAssembly(migrationsAssembly));};}).AddTestUsers(Config.GetUsers()).AddDeveloperSigningCredential();

3、appsettings.json中的配置

{
"ConnectionStrings": {"DefaultConnection": "Data Source=.;Initial Catalog=IndentityServer4;Persist Security Info=True;User ID=sa;Password=tony"}
}

4、执行迁移脚本

dotnet ef migrations add PersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/IdentityServer/PersistedGrantDb
dotnet ef migrations add ConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/IdentityServer/ConfigurationDb

5、迁移脚本生成数据库和表

dotnet ef database update -c PersistedGrantDbContext
dotnet ef database update -c ConfigurationDbContext

6、示例数据存储

           // 1、将config中数据存储起来private void InitializeDatabase(IApplicationBuilder app){using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope()){serviceScope.ServiceProvider.GetService<PersistedGrantDbContext>().Database.Migrate();var context = serviceScope.ServiceProvider.GetService<ConfigurationDbContext>();context.Database.Migrate();if (!context.Clients.Any()){foreach (var client in Config.GetClients()){context.Clients.Add(client.ToEntity());}context.SaveChanges();}if (!context.IdentityResources.Any()){foreach (var resource in Config.Ids){context.IdentityResources.Add(resource.ToEntity());}context.SaveChanges();}if (!context.ApiResources.Any()){foreach (var resource in Config.GetApiResources()){context.ApiResources.Add(resource.ToEntity());}context.SaveChanges();}}}

6、客户端进行访问

IdentityServer4 用户进行持久化(数据存储)

条件

1、Identity

步骤

1、Nuget安装Microsoft.AspNetCore.Identity.EntityFrameworkCore

2、添加上下文类

   public class IdentityServerUserDbContext : IdentityDbContext<IdentityUser>{public IdentityServerUserDbContext(DbContextOptions<IdentityServerUserDbContext> options) : base(options){}protected override void OnModelCreating(ModelBuilder builder){base.OnModelCreating(builder);}}

3、startup.cs文件配置

 services.AddDbContext<IdentityServerUserDbContext>(options =>{options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));});// 1.1 添加用户services.AddIdentity<IdentityUser, IdentityRole>(options => {// 1.2 密码复杂度配置options.Password.RequireDigit = true;options.Password.RequiredLength = 6;options.Password.RequiredUniqueChars = 1;options.Password.RequireLowercase = false;options.Password.RequireNonAlphanumeric = false;options.Password.RequireUppercase = false;}).AddEntityFrameworkStores<IdentityServerUserDbContext>().AddDefaultTokenProviders();

4、执行迁移脚本

 dotnet ef migrations add IdentityServerUserDbMigration -c IdentityServerUserDbContext -o Data/Migrations/IdentityServer/IdentityServerUserDb

5、迁移脚本生成数据库和表

dotnet ef database update -c IdentityServerUserDbContext

6、示例数据存储

// 2、将用户中数据存储起来private void InitializeUserDatabase(IApplicationBuilder app){using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope()){var context = serviceScope.ServiceProvider.GetService<IdentityServerUserDbContext>();context.Database.Migrate();
var userManager = serviceScope.ServiceProvider.GetRequiredService<UserManager<IdentityUser>>();var idnetityUser = userManager.FindByNameAsync("tony").Result;if (idnetityUser == null){idnetityUser = new IdentityUser{UserName = "zhangsan",Email = "zhangsan@email.com"};var result = userManager.CreateAsync(idnetityUser, "123456").Result;if (!result.Succeeded){throw new Exception(result.Errors.First().Description);}result = userManager.AddClaimsAsync(idnetityUser, new Claim[] {new Claim(JwtClaimTypes.Name, "tony"),new Claim(JwtClaimTypes.GivenName, "tony"),new Claim(JwtClaimTypes.FamilyName, "tony"),new Claim(JwtClaimTypes.Email, "tony@email.com"),new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),new Claim(JwtClaimTypes.WebSite, "http://tony.com")}).Result;if (!result.Succeeded){throw new Exception(result.Errors.First().Description);}}}}

6、AccountController修改Login代码

public class AccountController : Controller
{private UserManager<ApplicationUser> _userManager;private SignInManager<ApplicationUser> _signInManager;private IIdentityServerInteractionService _interaction;
public AccountController(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager, IIdentityServerInteractionService interaction)
{_userManager = userManager;_signInManager = signInManager;_interaction = interaction;
}
public IActionResult Login(string returnUrl)
{ViewData["ReturnUrl"] = returnUrl;return View();
}[HttpPost]
public async Task<IActionResult> Login(LoginViewModel loginViewModel, string returnUrl)
{// check if we are in the context of an authorization requestvar context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);// the user clicked the "cancel" buttonif (button != "login"){if (context != null){// if the user cancels, send a result back into IdentityServer as if they // denied the consent (even if this client does not require consent).// this will send back an access denied OIDC error response to the client.await _interaction.GrantConsentAsync(context, ConsentResponse.Denied);// we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-nullif (await _clientStore.IsPkceClientAsync(context.ClientId)){// if the client is PKCE then we assume it's native, so this change in how to// return the response is for better UX for the end user.return this.LoadingPage("Redirect", model.ReturnUrl);}return Redirect(model.ReturnUrl);}else{// since we don't have a valid context, then we just go back to the home pagereturn Redirect("~/");}}if (ModelState.IsValid){var user = await _userManager.FindByNameAsync(model.Username);if (user == null){ModelState.AddModelError(nameof(model.Username), $"用户名 {model.Username} not exists");}else{if (await _userManager.CheckPasswordAsync(user, model.Password)){AuthenticationProperties props = null;if (model.RememberLogin){props = new AuthenticationProperties{IsPersistent = true,ExpiresUtc = DateTimeOffset.UtcNow.Add(TimeSpan.FromMinutes(30))};}var isuser = new IdentityServerUser(user.Id){DisplayName = user.UserName};await HttpContext.SignInAsync(isuser, props);if (_interaction.IsValidReturnUrl(model.ReturnUrl)){return Redirect(model.ReturnUrl);}return Redirect("~/");}ModelState.AddModelError(nameof(model.Password), "密码错误");}}// something went wrong, show form with errorvar vm = await BuildLoginViewModelAsync(model);return View(vm);
}

}

ocelot集成 IdentityServer4

条件

1、IdentityServer4

步骤

1、Nuget安装IdentityServer4.AccessTokenValidation

2、在startup中文件配置IndentityServer4

// 1、配置IdentityServer
var authenticationProviderKey = "OcelotKey";services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme).AddIdentityServerAuthentication(options => {options.Authority = "http://localhost:5005"; // 1、授权中心地址options.ApiName = "TeamService"; // 2、api名称(项目具体名称)options.RequireHttpsMetadata = false; // 3、https元数据,不需要options.SupportedTokens = SupportedTokens.Both;});

3、 在ocelot.json中配置身份验证

"ReRoutes": [
{
"AuthenticationOptions": {"AuthenticationProviderKey": "OcelotKey","AllowedScopes": []}
}
]

ocelot集成 IdentityServer4 配置封装

条件

1、IdentityServerOptions类

步骤

1、创建IdentityServerOptions类

/// <summary>/// IdentityServer的配置选项/// </summary>public class IdentityServerOptions{/// <summary>/// 授权服务器的地址/// </summary>public int AuthorityAddress { get; set; }/// <summary>/// access_token的类型,获取access_token的时候返回参数中的token_type一致/// </summary>public string IdentityScheme { get; set; }/// <summary>/// 资源名称,认证服务注册的资源列表名称一致,/// </summary>public string ResourceName { get; set; }}

2、配置IdentityServerOptions

// 1、配置IdentityServer 增加配置选项
var identityServerOptions = new IdentityServerOptions();
Configuration.Bind("IdentityServerOptions", identityServerOptions);
var authenticationProviderKey = "OcelotKey";services.AddAuthentication(identityServerOptions.IdentityScheme).AddIdentityServerAuthentication(options => {options.Authority = identityServerOptions.AuthorityAddress; // 1、授权中心地址options.ApiName = identityServerOptions.ResourceName; // 2、api名称(项目具体名称)options.RequireHttpsMetadata = false; // 3、https元数据,不需要options.SupportedTokens = SupportedTokens.Both;});

ocelot动态路由

条件

1、consul

步骤

1、动态路由配置

{"ReRoutes": [],"Aggregates": [],"GlobalConfiguration": {"RequestIdKey": null,"ServiceDiscoveryProvider": {"Host": "localhost","Port": 8500,"Type": "Consul","Token": null,"ConfigurationKey": null},"RateLimitOptions": {"ClientIdHeader": "ClientId","QuotaExceededMessage": null,"RateLimitCounterPrefix": "ocelot","DisableRateLimitHeaders": false,"HttpStatusCode": 429},"QoSOptions": {"ExceptionsAllowedBeforeBreaking": 0,"DurationOfBreak": 0,"TimeoutValue": 0},"BaseUrl": null,"LoadBalancerOptions": {"Type": "LeastConnection","Key": null,"Expiry": 0},"DownstreamScheme": "https","HttpHandlerOptions": {"AllowAutoRedirect": false,"UseCookieContainer": false,"UseTracing": false}}
}

2、动态路由服务限流配置

{"DynamicReRoutes": [{"ServiceName": "TeamService","RateLimitRule": {"ClientWhitelist": [],"EnableRateLimiting": true,"Period": "1s","PeriodTimespan": 3000,"Limit": 3}}],"GlobalConfiguration": {"RequestIdKey": null,"ServiceDiscoveryProvider": {"Host": "localhost","Port": 8500,"Type": "Consul"},"RateLimitOptions": {"ClientIdHeader": "ClientId","QuotaExceededMessage": "","RateLimitCounterPrefix": "","DisableRateLimitHeaders": false,"HttpStatusCode": 428},"DownstreamScheme": "http"}
}

【.NET框架实战】IdentityServer4身份验证、授权相关推荐

  1. java中身份验证,如何处理数据库中用户的身份验证/授权?

    有几种选择 . 选择哪一项完全取决于您 . 只是客观地权衡具体的优缺点,以符合自己的情况 . 1.使用Java EE提供的容器管理身份验证 只需在 web.xml 中声明 ,它引用在servletco ...

  2. 身份验证协议和java安全框架

    一.身份验证协议 1.OAuth 关于 OAuth实际上是什么存在很多混淆.有些人认为 OAuth 是一种登录流程(例如,当您使用 Google Login 登录应用程序时),有些人认为 OAuth ...

  3. 使用JWT的ASP.NET CORE令牌身份验证和授权(无Cookie)——第2部分

    目录 介绍 用户角色 如何创建自定义授权特性? AuthorizeAttribute AuthorizeFilter 如何在控制器和操作方法级别设置权限? 检查用户权限的扩展方法 如何在操作方法(内联 ...

  4. 身份验证与授权(译)

    前言:身份验证与授权是网站开发比不可能绕开的话题,有趣的是,这两个单词的英文字母其实是很相似的,authentication and authorization,那么这两者到底有什么不同呢,下面翻译的 ...

  5. WEB安全基础入门—身份验证漏洞

    欢迎关注订阅专栏! WEB安全系列包括如下三个专栏:! <WEB安全基础-服务器端漏洞> <WEB安全基础-客户端漏洞> <WEB安全高级-综合利用> 知识点全面细 ...

  6. 网站如何经过身份验证_如何在微服务架构中实现安全性?

    首先为自己打个广告,我目前在某互联网公司做架构师,已经有5年经验,每天都会写架构师系列的文章,感兴趣的朋友可以关注我和我一起探讨,同时需要架构师资料的可以私信我免费送 作者 | Chris Richa ...

  7. 基于表单的网站身份验证的权威指南[关闭]

    基于表单的网站身份验证 我们认为Stack Overflow不仅应该是非常具体的技术问题的资源,而且还应该是关于如何解决常见问题变化的一般指导原则. "基于表单的网站身份验证"应该 ...

  8. HTTP/1.1(消息格式、连接管理、条件请求、范围请求、缓存、身份验证)

    文章目录 概述 消息格式 开始行 请求方法 请求目标 状态码 头部字段 消息体 连接管理 条件请求(Conditional Requests) 范围请求(Range Requests) 缓存(Cach ...

  9. 网站如何经过身份验证_微服务架构如何保证安全性?

    网络安全已成为每个企业都面临的关键问题.几乎每天都有关于黑客如何窃取公司数据的头条新闻. 为了开发安全的软件并远离头条新闻,企业需要解决各种安全问题,包括硬件的物理安全性.传输和静态数据加密.身份验证 ...

最新文章

  1. c语言习题与实验doc,[教材]C语言程序设计习题与上机实验(全部答案).doc
  2. extjs 限制上传文件类型_如何让extjg 支持选择多文件上传
  3. SpringBoot @Value、 @ConfigurationProperties 与 @EnableConfigurationProperties 使用
  4. CPU流水线的探秘之旅
  5. linux系统日常管理复习题讲解
  6. linux防火墙开启某端口命令行,linux上防火墙 开启某个端口
  7. node.js——麻将算法(五)胡牌算法的一些优化处理方案(有赖子版)
  8. linux chattr修改文件属性,linux chattr(改变文件属性)
  9. vuex辅助函数和vuex5个属性
  10. 我们常说的算法时间复杂度和空间复杂度到底是什么?
  11. putty登录到shell.sourceforge.net方法
  12. Java学习之正则表达式
  13. 8月7日晚八点分享-推荐系统面试/概览
  14. grads插值_利用grads描述文件中的pdef做插值的实用方法,转模式的同学看过来~~...
  15. SQL2005安装及连接
  16. 40家重污染行业上市公司进“黑名单”
  17. 肌酸报告:17个肌酸使用常见问题解答
  18. 摄像机DSP芯片介绍
  19. php捉迷藏,查看“蘑菇捉迷藏!”的源代码
  20. 手游大佬(日期模拟)

热门文章

  1. 第一次冲刺--查看活动详情用户场景分析
  2. 函数TEXT - EXCEL单元格中日期格式转换为文本格式
  3. java实现基本的购物车功能案例
  4. 金融业XIRR函数的算法思想与实现,java/plsql
  5. 推荐算法_CIKM-2019-AnalytiCup 冠军源码解读_2
  6. 信号完整性分析系列2——什么是信号完整性及何时遇到
  7. SpringBoot 封装返回类报错:No converter found for return value of type
  8. 如何获取目标基因的转录因子
  9. 【灵修】我去弘化禅寺一游——对学佛的理解(刘俊平)
  10. 微信开发者工具调试大法