IdentityServer4 1.0.0 documentation(官网)
.NET Core OAuth IdentityServer4 Token
IdentityServer4 Reference Token (Reference Token、Reference Token)
在 ASP.NET Core 中配置证书身份验证 (TLS,HTTPS 证书)
ASP.NET MVC 筛选器
身份验证和授权 IdentityServer、OpenID Connect 和 OAuth 2.0
ASP.NET Identity 基础表
GitHub IdentityServer4
GitHub SampleApi IdentityServer4 Startup.cs
GitHub SampleApi IdentityServer4 ConfirmationValidationMiddleware
ASP.Net Core下Authorization的几种方式 策略授权
authorize_Middleware_Sample
Middleware for security and authorization
Auth Permissions Demo
jwt.io
.NET 5 IdentityServer4 4.X版本配置
OAuth四种模式
● 授权码模式(authorization code)
● 简化模式(implicit)
● 密码模式(resource owner password credentials)
● 客户端模式(client credentials)
● 自定义 GrantType 授权模式
Authentication三大核心对象
● IAuthenticationSchemeProvider: ASP.NET Core 中可以支持各种各样的认证方式(如,cookie, bearer, oauth, openid 等等),而 Scheme 用来标识使用的是哪种认证方式,
● IAuthenticationHandlerProvider:负责对用户凭证的验证
● IAuthenticationService:本质上是对 IAuthenticationSchemeProvider 和 IAuthenticationHandlerProvider 封装,用来对外提供一个统一的认证服务接口
● IClaimsTransformation(不常用):一个对Claim进行转换的
AccessTokenType(JWT 和 Reference token)
JWT(JSON Web Token),是一种去中心化的验证方式
缺点:颁发服务器(授权认证服务器)无法集中控制 Token
Reference token
Reference token (有时也称 opaque token),Token 的有效与否是由 Token 颁发服务集中化控制的。接收者需要开辟一个连接到 token service 的反向通道 (back-channel),然后将 token 发送给一个 validation endpoint ,如果是合法的,则将检索到的内容作为响应。
对于 reference token 验证,提供了 access token validation endpoint 。比如,这个 endpoint 可以供我们的 access token 验证中间件使用,能够识别是 self-contained token 还是 reference token ,并且既可以在本地验证也可以使用 endpoint 来验证。所有的一切对于 API 来说都是透明的。
当使用 Reference token 的时候,服务端会对 Token 进行持久化,当客户端请求资源端(API)的时候,资源端需要每次都去服务端通信去验证 Token 的合法性[/connect/introspect],IdentityServer4.AccessTokenValidation 中间件中可以配置缓存一定的时候去验证,并且 Token 是支持撤销[/connect/revocation]的。
IdentityOptions
配置 ASP.NET Core 标识
业务逻辑
● 搭建 授权服务器 和 资源服务器
● 给App客户端发放 AppId 和 AppSecret
● 用户向App客户端提供自己的 账号 和 密码
● App客户端将AppId、AppSecret、账号、密码提交到 授权服务器
● 授权服务器通过授权,发放token和refresh_token
● 客户端通过 token 与 资源服务器 进行对接,并对 token 进行管理,防止失效
*
*
过滤器执行顺序
authorize(授权筛选器)--->resource(资源筛选器)--->action(操作筛选器)--->actionResult(结果筛选器),异常过滤器不分先后,只要抛出异常就会执行异常过滤器。
通过IOrderedFilter覆盖默认执行顺序,可以通过调整Order方法值大小来控制执行顺序,值越小,越先执行
[Route("api/[controller]")]
[MyFilter(Order = 1)]
public class ValuesController : Controller
{
}
*
认证(authentication) 就是 "判断用户有没有登录?",好比windows系统,没登录就无法使用。对应的是IIdentity接口
授权(authorization) 就是"用户登录后的身份/角色识别",好比"管理员用户"登录windows后,能安装软件、修改windows设置等所有操作。对应的是IPrincipal接口。
用户身份信息
Claim,ClaimsIdentity和ClaimsPrincipal
1、Authorize 命名空间
AuthorizeFilter -> Microsoft.AspNetCore.Mvc.Authorization
IAuthorizationFilter -> Microsoft.AspNetCore.Mvc.Filters
private readonly ILogger<IdentityController> _logger;
安全性、 身份验证和 ASP.NET Web API 中的授权
额外服务
AddExtensionGrantValidator
添加用于扩展授权的IExtensionGrantValidator实现。
AddSecretParser
添加用于解析客户端或API资源凭证的ISecretParser实现。
AddSecretValidator
添加ISecretValidator实现,以针对凭证存储验证客户端或API资源凭证。
AddResourceOwnerValidator
添加IResourceOwnerPasswordValidator`实现,用于验证资源所有者密码凭据授权类型的用户凭证。
AddProfileService
添加IProfileService以实现连接到您的自定义用户配置文件存储。DefaultProfileService`类提供了默认实现,它依靠身份验证cookie作为唯一的令牌发放源。
AddAuthorizeInteractionResponseGenerator
添加IAuthorizeInteractionResponseGenerator实现来在授权端点定制逻辑,以便显示用户错误,登录,同意或任何其他自定义页面的UI。 AuthorizeInteractionResponseGenerator类提供了一个默认的实现,因此如果需要增加现有的行为,可以考虑从这个现有的类派生。
AddCustomAuthorizeRequestValidator
添加ICustomAuthorizeRequestValidator实现,以在授权端点定制请求参数验证。
AddCustomTokenRequestValidator
添加ICustomTokenRequestValidator实现来定制令牌端点处的请求参数验证。
AddRedirectUriValidator
添加IRedirectUriValidator实现来自定义重定向URI验证。
AddAppAuthRedirectUriValidator
添加一个“AppAuth”(OAuth 2.0 for Native Apps)兼容的重定向URI验证器(进行严格的验证,但也允许随机端口为http://127.0.0.1)。
AddJwtBearerClientAuthentication
使用JWT对客户机认证的支持。
1、NuGet 引用
IdentityServer4
IdentityServer4.AccessTokenValidation
2、资源配置(Configurations\InMemoryConfiguration.cs)
using IdentityModel;
using IdentityServer4;
using IdentityServer4.Models;
using IdentityServer4.Test;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Security.Claims;
namespace Safe.IdentityServer.Configurations
{
public class InMemoryConfiguration
{
public static IConfiguration Configuration { get; set; }
public static IEnumerable<IdentityResource> GetIdentityResourceResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(), //必须要添加,否则报无效的scope错误
new IdentityResources.Profile(),
new IdentityResources.Email(),
new IdentityResource
{
Name = "role",
UserClaims = new List<string> {"role"}
}
};
}
/// <summary>
/// Define which APIs will use this IdentityServer
/// </summary>
/// <returns></returns>
public static IEnumerable<ApiResource> GetApiResources()
{
new List<ApiResource>
{
new ApiResource("api1", "My API")
};
return new[]
{
new ApiResource("clientservice", "CAS Client Service"),
new ApiResource("productservice", "CAS Product Service"),
new ApiResource("agentservice", "CAS Agent Service"),
new ApiResource
{
Name = "customAPI",
DisplayName = "Custom API",
Description = "Custom API Access",
UserClaims = new List<string> {"role"},
ApiSecrets = new List<Secret> {new Secret("scopeSecret".Sha256())},
Scopes = new List<Scope>
{
new Scope("customAPI.read"),
new Scope("customAPI.write")
}
}
};
}
public static IEnumerable<ApiResource> GetResources()
{
return new List<ApiResource>
{
new ApiResource
{
Name = "ImageResource",
Scopes ={new Scope ("ImageResource")},//Scopes必须配置,否则获取token时返回 invalid_scope
},
new ApiResource
{
Name = "FileResourse"
},
new ApiResource
{
Name ="Api",
Scopes = { new Scope ("Api") }
}
};
}
/// <summary>
/// 授权模式:客户端模式 GrantTypes.ClientCredentials
/// </summary>
/// <returns></returns>
public static IEnumerable<Client> GetClientsNew()
{
return new List<Client>
{
// client credentials client
new Client
{
ClientId = "client1",
ClientName = "Example Client Credentials Client Application",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes =
{
"http://localhost:3000",
IdentityServerConstants.StandardScopes.OpenId, //必须要添加,否则报forbidden错误
IdentityServerConstants.StandardScopes.Profile
},
},
// resource owner password grant client
new Client
{
ClientId = "client2",
ClientName = "Example Client Credentials Client Application",
AccessTokenType = AccessTokenType.Jwt,
//AccessTokenType = AccessTokenType.Reference,
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
UpdateAccessTokenClaimsOnRefresh = true,
AllowOfflineAccess = true, // 刷新token
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes =
{
"http://localhost:3000",
IdentityServerConstants.StandardScopes.OpenId, //必须要添加,否则报forbidden错误
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.OfflineAccess,
}
},
new Client
{
ClientId = "ClientId",
ClientName = "Example Client Credentials Client Application",
AllowedGrantTypes = GrantTypes.ClientCredentials,//授权模式:客户端模式
AllowedScopes =
{
"ImageResource",
"Api"
}, //允许访问的资源 GetResources()中配置的
ClientSecrets = { new Secret { Value = "ClientSecret".Sha256(), Expiration =DateTime.Now.AddMinutes(5)}}
},
new Client
{
ClientId = "openIdConnectClient",
ClientName = "Example Implicit Client Application",
AllowedGrantTypes = GrantTypes.Implicit,
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"role",
"customAPI.write"
},
RedirectUris = new List<string> {"https://localhost:44330/signin-oidc"},
PostLogoutRedirectUris = new List<string> {"https://localhost:44330"}
}
};
}
/// <summary>
/// Define which Apps will use thie IdentityServer
/// </summary>
/// <returns></returns>
public static IEnumerable<Client> GetClients()
{
return new[]
{
new Client
{
ClientId = "client.api.service",
ClientName = "Example Client Credentials Client Application",
ClientSecrets = new [] { new Secret("clientsecret".Sha256()) },
AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
AllowedScopes = new [] { "clientservice" }
},
new Client
{
ClientId = "product.api.service",
ClientName = "Example Client Credentials Client Application",
ClientSecrets = new [] { new Secret("productsecret".Sha256()) },
AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
AllowedScopes = new [] { "clientservice", "productservice" }
},
new Client
{
ClientId = "agent.api.service",
ClientName = "Example Client Credentials Client Application",
ClientSecrets = new [] { new Secret("agentsecret".Sha256()) },
AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
AllowedScopes = new [] { "agentservice", "clientservice", "productservice" }
}
};
}
/// <summary>
/// ids4 4.X 新特性【注意:每个scope的值不能相同,否则报错】
/// </summary>
/// <returns></returns>
public static IEnumerable<ApiScope> GetScopes()
{
return new ApiScope[]
{
new ApiScope("Asset"),
new ApiScope(ConfigManager.Configuration["IdentityAuthentication:Scope"]),
};
}
/// <summary>
/// ids4 4.X 新特性【注意:每个scope的值不能相同,否则报错】
/// </summary>
public static IEnumerable<ApiScope> ApiScopes =>
new ApiScope[]
{
new ApiScope("Asset"),
new ApiScope(ConfigManager.Configuration["IdentityAuthentication:Scope"]),
};
/// <summary>
/// Define which uses will use this IdentityServer
/// </summary>
/// <returns></returns>
public static IEnumerable<TestUser> GetUsers()
{
return new[]
{
new TestUser
{
SubjectId = "10001",
Username = "edison@hotmail.com",
Password = "edisonpassword"
},
new TestUser
{
SubjectId = "10002",
Username = "andy@hotmail.com",
Password = "andypassword"
},
new TestUser
{
SubjectId = "10003",
Username = "leo@hotmail.com",
Password = "leopassword"
},
new TestUser
{
SubjectId = "5BE86359-073C-434B-AD2D-A3932222DABE",
Username = "scott",
Password = "password",
Claims = new List<Claim>
{
new Claim(JwtClaimTypes.Email, "scott@scottbrady91.com"),
new Claim(JwtClaimTypes.Role, "admin")
}
}
};
}
}
}
3、配置 IdentityServer(Startup.cs文件)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
namespace Safe.IdentityServer
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// IdentityOptions 根据自己情况编写
services.Configure<IdentityOptions>(options =>
{
// Password settings.密码配置
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequiredLength = 6;
options.Password.RequiredUniqueChars = 1;
// Lockout settings.锁定设置
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.AllowedForNewUsers = true;
// User settings.用户设置
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
options.User.RequireUniqueEmail = false;
});
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(Configurations.InMemoryConfiguration.GetApiResources())
.AddInMemoryClients(Configurations.InMemoryConfiguration.GetClients());
#region ids4 4.X 新特性
.AddInMemoryApiScopes(Security.IdentityConfig.GetScopes())
//.AddInMemoryApiScopes(Security.IdentityConfig.ApiScopes)
#endregion
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseIdentityServer();//使用IdentityServer授权服务
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
}
}
}
4、启动项目,浏览器输入 https://localhost:44305/.well-known/openid-configuration 查看文档(端口号以项目运行的真实地址为准)
{
"issuer": "https://localhost:44305",//发行网址,也就是说我们的权限验证站点
"jwks_uri": "https://localhost:44305/.well-known/openid-configuration/jwks",
"authorization_endpoint": "https://localhost:44305/connect/authorize",//授权服务器的授权端点的URL
"token_endpoint": "https://localhost:44305/connect/token",//获取token的网址
"userinfo_endpoint": "https://localhost:44305/connect/userinfo",//根据token获取用户信息
"end_session_endpoint": "https://localhost:44305/connect/endsession",//登录注销
"check_session_iframe": "https://localhost:44305/connect/checksession",//客户端对check_session_iframe执行监视,可以获取用户的登出状态
"revocation_endpoint": "https://localhost:44305/connect/revocation",//撤销访问令牌(仅access tokens 和reference tokens)。它实现了令牌撤销规范(RFC 7009)
"introspection_endpoint": "https://localhost:44305/connect/introspect",//验证reference tokens
"device_authorization_endpoint": "https://localhost:44305/connect/deviceauthorization",
"frontchannel_logout_supported": true,//可选。基于前端的注销机制
"frontchannel_logout_session_supported": true,//可选。基于session的注销机制
"backchannel_logout_supported": true,//指示OP支持后端通道注销
"backchannel_logout_session_supported": true,
"scopes_supported": [
"clientservice",
"productservice",
"agentservice",
"customAPI.read",
"customAPI.write",
"offline_access"
],
"claims_supported": [
"role"
],
"grant_types_supported": [
"authorization_code",
"client_credentials",
"refresh_token",
"implicit",
"urn:ietf:params:oauth:grant-type:device_code"
],
"response_types_supported": [
"code",
"token",
"id_token",
"id_token token",
"code id_token",
"code token",
"code id_token token"
],
"response_modes_supported": [
"form_post",
"query",
"fragment"
],
"token_endpoint_auth_methods_supported": [
"client_secret_basic",
"client_secret_post"
],
"subject_types_supported": [
"public"
],
"id_token_signing_alg_values_supported": [
"RS256"
],
"code_challenge_methods_supported": [
"plain",
"S256"
]
}
5、
6、
7、
8、