ASP.NET_.NET

ASP.NET_.NET我们在《ASP.NETCore项目实战的课程》第一章里面给identityserver4做了一个全面的介绍和示例的练习。如果想完全理解本文所涉及到的话题,你需要了解的背景知识有:什么是OpenIdConnect(OIDC)OIDC对oAuth进行了哪些扩展?IdentityServer4提供的OIDC认证服务(服务端)ASP.NETCore的权限体系中的OIDC认证框架(客户端)什

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

我们在《ASP.NET Core项目实战的课程》第一章里面给identity server4做了一个全面的介绍和示例的练习 。

如果想完全理解本文所涉及到的话题,你需要了解的背景知识有:

  • 什么是OpenId Connect (OIDC)

  • OIDC 对oAuth进行了哪些扩展?

  • Identity Server4提供的OIDC认证服务(服务端)

  • ASP.NET Core的权限体系中的OIDC认证框架(客户端)

什么是 OIDC

在了解OIDC之前,我们先看一个很常见的场景。假使我们现在有一个网站要集成微信或者新浪微博的登录,两者现在依然采用的是oAuth 2.0的协议来实现 。 关于微信和新浪微博的登录大家可以去看看它们的开发文档。

在我们的网站集成微博或者新浪微博的过程大致是分为五步:

  1. 准备工作:在微信/新浪微博开发平台注册一个应用,得到AppId和AppSecret

  2. 发起 oAauth2.0 中的 Authorization Code流程请求Code

  3. 根据Code再请求AccessToken(通常在我们应用的后端完成,用户不可见)

  4. 根据 AccessToken 访问微信/新浪微博的某一个API,来获取用户的信息

  5. 后置工作:根据用户信息来判断是否之前登录过?如果没有则创建一个用户并将这个用户作为当前用户登录(我们自己应用的登录逻辑,比如生成jwt),如果有了则用之前的用户登录。

中间第2到3的步骤为标准的oAuth2 授权码模式的流程,如果不理解的可以参考阮一峰所写的《理解oAuth2.0 》一文。我们主要来看第4和5步,对于第三方应用要集成微博登录这个场景来说最重要的是我希望能快速拿到用户的一些基本信息(免去用户再次输入的麻烦)然后根据这些信息来生成一个我自己的用户跟微博的用户Id绑定(为的是下次你使用微博登录的时候我还能把你再找出来)。

oAuth在这里麻烦的地方是我还需要再请求一次API去获取用户数据,注意这个API和登录流程是不相干的,其实是属于微博开放平台丛多API中的一个,包括微信开放平台也是这样来实现。这里有个问题是前面的 2和3是oAuth2的标准化流程,而第4步却不是,但是大家都这么干(它是一个大家都默许的标准)

于是大家干脆就建立了一套标准协议并进行了一些优化,它叫OIDC

OIDC 建立在oAuth2.0协议之上,允许客户端(Clients)通过一个授权服务(Authorization Server)来完成对用户认证的过程,并且可以得到用户的一些基本信息包含在JWT中。

OIDC对oAuth进行了哪些扩展?

在oAuth2.0授权码模式的帮助下,我们拿到了用户信息。

ASP.NET_.NET

上没有认证的过程,只是给我们的应用授权访问一个API的权限,我们通过这个API去获取当前用户的信息,这些都是通过oAuth2的授权码模式完成的。 我们来看看oAuth2 授权码模式的流程:

第一步,我们向authorize endpoint请求code的时候所传递的response_type表示授权类型,原来只有固定值code

GET /connect/authorize?response_type=code&client_id=postman&state=xyz&scope=api1        &redirect_uri=http://localhost:5001/oauth2/callback

第二步,上面的请求执行完成之后会返回301跳转至我们传过去的redirect_uri并带上code

https://localhost:5001/oauth2/callback?code=835d584d4bc96d46ce49e27ebdbf272e40234d5f31097f63163f17da61fcd01c&scope=api1&state=111271607

第三步,用code换取access token

POST /connect/token?grant_type=authorization_code&code=835d584d4bc96d46ce49e27ebdbf272e40234d5f31097f63163f17da61fcd01c&redirect_uri=http://localhost:5001/oauth2/callback&client_id=postman&client_secret=secret

通过这个POST我们就可以得到access_token

{    "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjV",    "expires_in": 3600,    "token_type": "Bearer"}

我们拿到access_token之后,再把access_token放到authorization头请求 api来获取用户的信息。在这里,这个api不是属于授权服务器提供的,而是属于资源服务器。

OIDC给oAuth2进行扩展之后就填补了这个空白,让我们可以授权它添加了以下两个内容:

  • response_type 添加IdToken

  • 添加userinfo endpoint,用idToken可以获取用户信息

OIDC对它进行了扩展,现在你有三个选择:code, id_token和 token,现在我们可以这样组合来使用。

“response_type” value Flow
code Authorization Code Flow
id_token Implicit Flow
id_token token Implicit Flow
code id_token Hybrid Flow
code token Hybrid Flow
code id_token token Hybrid Flow

我们简单的来理解一下这三种模式:

  • Authorization Code Flow授权码模式:保留oAuth2下的授权模式不变response_type=code

  • Implicit Flow 隐式模式:在oAuth2下也有这个模式,主要用于客户端直接可以向授权服务器获取token,跳过中间获取code用code换accesstoken的这一步。在OIDC下,responsetype=token idtoken,也就是可以同时返回access_token和id_token。

  • Hybrid Flow 混合模式: 比较有典型的地方是从authorize endpoint 获取 code idtoken,这个时候id_token可以当成认证。而可以继续用code获取access_token去做授权,比隐式模式更安全。

    再来详细看一下这三种模式的差异:

Property Authorization Code Flow Implicit Flow Hybrid Flow
access token和id token都通过Authorization endpoint返回 no yes no
两个token都通过token end point 返回 yes no no
用户使用的端(浏览器或者手机)无法查看token yes no no
Client can be authenticated yes no yes
支持刷新token yes no yes
不需要后端参与 no yes no

我们来看一下通过Hybird如何获取 code、id_token、_以及access_token,然后再用id_token向userinfo endpoint请求用户信息。

第一步:获取code,

  • response_type=code id_token

  • scope=api1 openid profile 其中openid即为用户的唯一识别号

GET /connect/authorize?response_type=code id_token&client_
id
=postman&state=xyz&scope=api1 openid profile&nonc
e
=7362CAEA-9CA5-4B43-9BA3-34D7C303EBA7 &r
edirect_uri
=http://localhost:5001/oauth2/callback

当我们使用OIDC的时候,我们请求里面多了一个nonce的参数,与state有异曲同工之妙。我们给它一个guid值即可。

第二步:我们的redirect_uri在接收的时候即可以拿到code 和 id_token

https://localhost:5001/oauth2/callback#code=c5eaaaca8d4538f69f670a900d7a4fa1d1300b26ec67fba2f84129f0ab4ffa35&id_token=eyJhbGciOiJSUzI1NiIsImtpZCI6IjVjMzA5ZGIwYTE2OGEwOTgGtpbj0GVXNnkKhGdrzA&scope=openid%20profile%20api1&state=111271607

第三步:用code换access_token(这一步与oAuth2中的授权码模式一致)

第四步:用access_token向userinfo endpoint获取用户资料

Get http://localhost:5000/connect/userinfo
Authorization Bearer access_token

返回的用户信息

{    "name": "scott",    "family_name": "liu",    "sub": "5BE86359-073C-434B-AD2D-A3932222DABE"}

以下是我们的流程示意图。

ASP.NET_.NET

可能会注意到,在这里我们拿到的idtoken没有派上用场,我们的用户资料还是通过access_token从userinfo endpoint里拿的。这里有两个区别:

  1. userinfo endpoint是属于认证服务器实现的,并非资源服务器,有归属的区别

  2. id_token 是一个jwt,里面带有用户的唯一标识,我们在判断该用户已经存在的时候不需要再请求userinfo endpoint

下图是对id_token进行解析得到的信息:sub即subject_id(用户唯一标识 )

ASP.NET_.NET

jwt了解的同学知道它里面本身就可以存储用户的信息,那么id_token可以吗?答案当然是可以的,我们将在介绍完identity server4的集成之后最后来实现。

Identity Server4提供的OIDC认证服务

Identity Server4是asp.net core2.0实现的一套oAuth2 和OIDC框架,用它我们可以很快速的搭建一套自己的认证和授权服务。我们来看一下用它如何快速实现OIDC认证服务。

由于用户登录代码过多,完整代码可以加入ASP.NET Core QQ群 92436737获取。 此处仅展示配置核心代码。

过程

  • 新建asp.net core web应用程序

  • 添加identityserver4 nuget引用

  • 依赖注入初始化

services.AddIdentityServer()              
.AddDeveloperSigningCredential()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(Config.GetTestUsers());
  • 中间件添加

app.UseIdentityServer();
  • 配置

在测试的时候我们新建一个Config.cs来放一些配置信息

api resources

public static IEnumerable<ApiResource> GetApiResources()
        {           
return new List<ApiResource> {
new ApiResource("api1", "API Application"){ UserClaims = { "role", JwtClaimTypes.Role } } }; }

identity resources

public static IEnumerable<IdentityResource> GetIdentityResources()
        {           
return new List<IdentityResource> {
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Email(), }; }

clients

我们要讲的关键信息在这里,client有一个AllowGrantTypes它是一个string的集合。我们要写进去的值就是我们在上一节讲三种模式: Code,Implict和Hybird。因为这三种模式决定了我们的response_type可以请求哪几个值,所以这个地方一定不能写错。

IdentityServer4.Models.GrantTypes这个枚举给我们提供了一些选项,实际上是把oAuth的4种和OIDC的3种进行了组保。

public static IEnumerable<Client> GetClients()
        {            return new List<Client>
            {                new Client
                {
                    ClientId = "postman",

                    AllowedGrantTypes = GrantTypes.Hybird,
                    RedirectUris = { "https://localhost:5001/oauth2/callback" },

                    ClientSecrets =
                    {                        new Secret("secret".Sha256())
                    },

                     AllowedScopes = new List<string>
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,                        "api1"
                    },

                    AllowOfflineAccess=true,

                },
            };
        }

users

public static List<TestUser> GetTestUsers()
{         
return new List<TestUser> {
new TestUser { SubjectId = "5BE86359-073C-434B-AD2D-A3932222DABE", Username = "scott", Password = "password", Claims = new List<Claim> {
new Claim(JwtClaimTypes.Name, "scott"),
new Claim(JwtClaimTypes.FamilyName, "liu"),
new Claim(JwtClaimTypes.Email, "scott@scottbrady91.com"),
new Claim(JwtClaimTypes.Role, "user"),
} } }; }

ASP.NET Core的权限体系中的OIDC认证框架

在Microsoft.AspNetCore.All nuget引用中包含了Microsoft.AspNetCore.Authentication.OpenIdConnect即asp.net core OIDC的客户端。我们需要在依赖注入中添加以下配置:

services.AddAuthentication(options =>
            {
                options.DefaultScheme = "Cookies";
                options.DefaultChallengeScheme = "oidc";
            })
          .AddCookie("Cookies")
          .AddOpenIdConnect("oidc", options =>
          {
              options.SignInScheme = "Cookies";
              options.Authority = "http://localhost:5000";
              options.RequireHttpsMetadata = false;
              options.ClientId = "postman";
              options.ClientSecret = "secret";
              options.ResponseType = "code id_token";
              options.GetClaimsFromUserInfoEndpoint = true;
              options.Scope.Add("api1");
              options.Scope.Add("offline_access");
          });

Authority即我们的用identity server4搭建的认证授权服务器,而其中的GetClaimsFromUserInfoEndpoint则会在拿到id_token之后自动向userinfo endpoint请求用户信息并放到asp.net core的User Identity下。

我们上面讲过,可以不需要请求userinfo endpoint, 直接将用户信息放到id_token中。

样我们就不需要再向userinfo endpoint发起请求,从id_token中即可以获取到用户的信息。而有了identity server4的帮助,完成这一步只需要一句简单的配置即可:

new Client
{    ClientId = "postman",

    AlwaysIncludeUserClaimsInIdToken = true,
    AllowOfflineAccess=true,
}

 这样我们在拿到id_token之后,里即包含了我们的用户信息。

ASP.NET_.NET

相关文章:

原文地址:https://github.com/jessetalk/aspnet-core-in-practise/blob/master/chapter1.md 


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

ASP.NET_.NET

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/180049.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 在Java中实现UDP协议编程(DatagramSocket/DatagramPacket)「建议收藏」

    在Java中实现UDP协议编程(DatagramSocket/DatagramPacket)「建议收藏」1.什么是UDP协议?UDP(UserDatagramProtocol)协议是用户数据报,在网络中它与TCP协议一样用于处理数据包。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的源或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。

  • stimulsoft oracle,报表仪表设计器Stimulsoft的处理数据功能

    stimulsoft oracle,报表仪表设计器Stimulsoft的处理数据功能StimulsoftReports.Net是一个基于.NET框架的报表生成器,能够帮助你创建结构、功能丰富的报表。StimulReport.Net的报表设计器不仅界面友好,而且使用便捷,能够让你轻松创建所有报表;该报表设计器在报表设计过程中以及报表运行的过程中都可以使用。在运行时使用StimulReport.Net的报表设计器不需要支付任何的专利费用。所创建的报表既可以在Windows窗体应用…

  • Ubuntu安装配置MySQL_nginx upstream

    Ubuntu安装配置MySQL_nginx upstream系Ubuntu安装配置nginx提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加例如:第一章Python机器学习入门之pandas的使用提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录系Ubuntu安装配置nginx前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结前言提示:这里可以添加本文要记录的大概内容:例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。

  • 内核态和用户态区别的重要性_cpu用户态和内核态区别

    内核态和用户态区别的重要性_cpu用户态和内核态区别内核态和用户态区别内核态和用户态区别当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。此时处理器处于特权级最高的(0级)内核代码中执行。当进程处于内核态时,执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈。当进程在执行用户自己的代码时,则称其处于用户运行态(用户态)。即此时处理器在特权级最低的(3级)用户代码中运行。当正在

  • mac clion激活码破解方法

    mac clion激活码破解方法,https://javaforall.cn/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

  • python爬取豆瓣电影榜单

    python爬取豆瓣电影榜单python爬取豆瓣电影榜单python爬取豆瓣电影榜单并保存到本地excel中,以后就不愁没片看了。目标确定我们想要抓取的电影的相关内容。抓取豆瓣top250电影的排名、电影名、评价(总结很到位)、评分、点评人数及电影的豆瓣页面。抓取各种电影类型的排行榜前100。编码省略需求到编码中间的繁文缛节,直接上手编码。(此处是最终编码)目标一使用BeautifulSoup解析页面查找元素。目标二调用接口处理返回的json数据。importrequestsimportopenpyx

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号