OAuth 身份认证 IdentityServer4

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、

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值