IdentityServer4 (3) 授权码模式(Authorization Code)
写在前面
1、源码(.Net Core 2.2)
git地址:https://github.com/yizhaoxian/CoreIdentityServer4Demo.git
2、相关章节
2.1、《IdentityServer4 (1) 客户端授权模式(Client Credentials)》
2.2、《IdentityServer4 (2) 密码授权(Resource Owner Password)》
2.3、《IdentityServer4 (3) 授权码模式(Authorization Code)》
2.4、《IdentityServer4 (4) 静默刷新(Implicit)》
2.5、《IdentityServer4 (5) 混合模式(Hybrid)》
3、参考资料
IdentityServer4 中文文档 http://www.identityserver.com.cn/
IdentityServer4 英文文档 https://identityserver4.readthedocs.io/en/latest/
OpenID Connect 官网 https://openid.net/connect/
OpenID Connect 中文 https://www.cnblogs.com/linianhui/p/openid-connect-core.html
OpenID Connect和OAuth 2.0对比:https://www.jianshu.com/p/d453076e6433
4、流程图
1、访问客户端受保护的url
2、跳转到授权服务器认证
3、用户填写认证(账号密码)
4、认证成功,选择授权的scope
5、授权成功(点击同意授权),携带授权码code返回客户端
6、客户端通过后台通信请求AccessToken 和IdToken,如果设置了 OfflineAccess=true也会返回RefreshToken(可以刷新AccessToken)
整个访问流程建议使用fiddler 抓包查看,更好的了解
一、服务端
1、下载一个官方示例
地址:https://github.com/IdentityServer/IdentityServer4.Quickstart.UI
根据自己使用的Core 版本下载对应的,点击 tags 里找,我下载的是2.5,解压后如下图
2、新建一个 web 项目 .NetCore 2.2版本
把官网下载的文件添加到项目中,Quickstart 我换成了Controllers
3、添加配置类 (IdpConfig.cs)
参看 《IdentityServer4 (1) 客户端授权模式(Client Credentials)》里的,直接复制过来就可以了
4、添加客户端
IdpConfig.cs GetClients()
AllowedScopes 属性设置的值,必须在GetApiResources() GetApis() 里提前定义好,并且在 StartUp.cs 里已经注册
- new Client{
- ClientId="mvc client", //客户端Id
- ClientName="测试客户端", //客户端名称 随便写
- AllowedGrantTypes=GrantTypes.Code,//验证模式
- ClientSecrets=
- {
- new Secret("mvc secret".Sha256()) //客户端验证密钥
- },
- // 登陆以后 我们重定向的地址(客户端地址),
- // {客户端地址}/signin-oidc是系统默认的不用改,也可以改,这里就用默认的
- RedirectUris = { "http://localhost:5003/signin-oidc" },
- //注销重定向的url
- PostLogoutRedirectUris = { "http://localhost:5003/signout-callback-oidc" },
- //是否允许申请 Refresh Tokens
- //参考地址 https://identityserver4.readthedocs.io/en/latest/topics/refresh_tokens.html
- AllowOfflineAccess=true,
- //将用户claims 写人到IdToken,客户端可以直接访问
- AlwaysIncludeUserClaimsInIdToken=true,
- //客户端访问权限
- AllowedScopes =
- {
- "api1",
- IdentityServerConstants.StandardScopes.OpenId,
- IdentityServerConstants.StandardScopes.Email,
- IdentityServerConstants.StandardScopes.Address,
- IdentityServerConstants.StandardScopes.Phone,
- IdentityServerConstants.StandardScopes.Profile,
- IdentityServerConstants.StandardScopes.OfflineAccess
- }
- }
5、注册相关信息(StartUp.cs)
ConfigureServices() 注意这里我修改了路径,如果你使用的是 git 下载下来的不需要修改,我这里修改是我把 git 下载的改动了
- services.AddIdentityServer(options =>
- {
- //默认的登陆页面是/account/login
- options.UserInteraction.LoginUrl = "/login";
- //授权确认页面 默认/consent
- //options.UserInteraction.ConsentUrl = "";
- })
- .AddDeveloperSigningCredential()
- .AddInMemoryApiResources(IdpConfig.GetApis())
- .AddInMemoryClients(IdpConfig.GetClients())
- .AddTestUsers(TestUsers.Users)
- .AddInMemoryIdentityResources(IdpConfig.GetApiResources());
Configure()
- // 要写在 UseMvc()前面
- app.UseIdentityServer();
- app.UseMvcWithDefaultRoute();
二、客户端
1、添加认证相关信息(StartUp.cs)
ConfigureServices()
- //关闭了 JWT 身份信息类型映射
- //这样就允许 well-known 身份信息(比如,“sub” 和 “idp”)无干扰地流过。
- //这个身份信息类型映射的“清理”必须在调用 AddAuthentication()之前完成
- //区别可参考下面截图
- JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
- //添加认证信息
- services.AddAuthentication(options =>
- {
- options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
- options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
- })
- .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
- .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
- {
- options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
- //认证服务器
- options.Authority = "http://localhost:5002";
- //去掉 https
- options.RequireHttpsMetadata = false;
- options.ClientId = "mvc client";
- options.ClientSecret = "mvc secret";
- //把 token 存储到 cookie
- options.SaveTokens = true;
- options.ResponseType = OpenIdConnectResponseType.Code;
- //添加申请 权限 ,这里的 scope 必须在授权服务端定义的客户端 AllowedScopes 里
- options.Scope.Clear();
- options.Scope.Add("api1");
- options.Scope.Add(OidcConstants.StandardScopes.OpenId);
- options.Scope.Add(OidcConstants.StandardScopes.Email);
- options.Scope.Add(OidcConstants.StandardScopes.Address);
- options.Scope.Add(OidcConstants.StandardScopes.Phone);
- options.Scope.Add(OidcConstants.StandardScopes.Profile);
- options.Scope.Add(OidcConstants.StandardScopes.OfflineAccess);
- options.Events = new OpenIdConnectEvents
- {
- OnAuthenticationFailed = context =>
- {
- context.HandleResponse();
- context.Response.WriteAsync("验证失败");
- return Task.CompletedTask;
- }
- };
- });
Configure()
- //写在 UseMvc() 前面
- app.UseAuthentication();
- app.UseMvcWithDefaultRoute();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); 区别
2、添加测试Controller
- [Authorize]
- public class TestController : Controller
- {
- /// <summary>
- /// 测试从服务端认证
- /// </summary>
- /// <returns></returns>
- public async Task<IActionResult> Private()
- {
- var accessToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.AccessToken);
- var idToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.IdToken);
- var refreshToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.RefreshToken);
- var code = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.Code);
- var model = new HomeViewModel
- {
- Infos = new Dictionary<string, string>()
- {
- {"AccessToken", accessToken },
- {"IdToken", idToken },
- {"RefreshToken", refreshToken },
- {"Code", code } //code 是空 因为code 是一次性的
- }
- };
- return View(model);
- }
- /// <summary>
- /// 测试请求API资源(api1)
- /// </summary>
- /// <returns></returns>
- public async Task<IActionResult> SuiBian()
- {
- var accesstoken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.AccessToken);
- if (string.IsNullOrEmpty(accesstoken))
- {
- return Json(new { msg = "accesstoken 获取失败" });
- }
- var client = new HttpClient();
- client.SetBearerToken(accesstoken);
- var httpResponse = await client.GetAsync("http://localhost:5001/api/suibian");
- var result = await httpResponse.Content.ReadAsStringAsync();
- if (!httpResponse.IsSuccessStatusCode)
- {
- return Json(new { msg = "请求 api1 失败。", error = result });
- }
- return Json(new
- {
- msg = "成功",
- data = JsonConvert.DeserializeObject(result)
- });
- }
- }
三、API资源
参考上一篇《IdentityServer4 (1) 客户端授权模式》
修改SuiBianController.Get()
- [HttpGet]
- public IActionResult Get()
- {
- return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
- }
四、测试
1、端口说明
【客户端:5003】【 API :5001 】【 授权认证服务器:5002】,并确认3个端口可以正常访问
2、客户端访问
2.1 、输入地址:http://localhost:5003/test/private 查看是否可正常跳转到授权服务器,
2.2、正常跳转,输入账号(alice)密码(alice)并登陆。登陆成功,并显示可授权的信息
2.3、点击授权同意,返回相关授权信息,并展示在页面
2.4 、输入地址 http://localhost:5003/test/suibian 访问 API 资源,正确返回
IdentityServer4 (3) 授权码模式(Authorization Code)的更多相关文章
- 基于OWIN WebAPI 使用OAUTH2授权服务【授权码模式(Authorization Code)】
之前已经简单实现了OAUTH2的授权码模式(Authorization Code),但是基于JAVA的,今天花了点时间调试了OWIN的实现,基本就把基于OWIN的OAUHT2的四种模式实现完了.官方推 ...
- Apache Oltu 实现 OAuth2.0 服务端【授权码模式(Authorization Code)】
要实现OAuth服务端,就得先理解客户端的调用流程,服务提供商实现可能也有些区别,实现OAuth服务端的方式很多,具体可能看 http://oauth.net/code/ 各语言的实现有(我使用了Ap ...
- IdentityServer4系列 | 授权码模式
一.前言 在上一篇关于简化模式中,通过客户端以浏览器的形式请求IdentityServer服务获取访问令牌,从而请求获取受保护的资源,但由于token携带在url中,安全性方面不能保证.因此,我们可以 ...
- OAuth 第三方登录授权码(authorization code)方式的小例子
假如上面的网站A,可以通过GitHub账号登录: 下面以OAuth其中一种方式,授权码(authorization code)方式为例. 一.第三方登录的原理 所谓第三方登录,实质就是 OAuth 授 ...
- OAuth 白话简明教程 2.授权码模式(Authorization Code)
转自:http://www.cftea.com/c/2016/11/6703.asp OAuth 白话简明教程 1.简述 OAuth 白话简明教程 2.授权码模式(Authorization Code ...
- OAuth2.0 授权许可 之 Authorization Code
写在前面: 在前一篇博客<OAuth2.0 原理简介>中我们已经了解了OAuth2.0的原理以及它是如何工作的,那么本篇我们将来聊一聊OAuth的一种授权许可方式:授权码(Authoriz ...
- asp.net权限认证:OWIN实现OAuth 2.0 之授权码模式(Authorization Code)
asp.net权限认证系列 asp.net权限认证:Forms认证 asp.net权限认证:HTTP基本认证(http basic) asp.net权限认证:Windows认证 asp.net权限认证 ...
- IdentityServer4实现OAuth2.0四种模式之授权码模式
接上一篇:IdentityServer4实现OAuth2.0四种模式之隐藏模式 授权码模式隐藏码模式最大不同是授权码模式不直接返回token,而是先返回一个授权码,然后再根据这个授权码去请求token ...
- IdentityServer4系列[6]授权码模式
授权码模式是一种混合模式,是目前功能最完整.流程最严密的授权模式.它主要分为两大步骤:认证和授权.其流程为: 用户访问客户端,客户端将用户导向Identity Server. 用户填写凭证信息向客户端 ...
随机推荐
- JVM 专题一:虚拟机(一)
1. 虚拟机 1.1 什么是虚拟机? 虚拟机(Virtual Machine)指通过软件模拟的具有完整硬件系统功能的.运行在一个完全隔离环境中的完整计算机系统. 所谓虚拟机,就是一台虚拟的计算机.它是 ...
- 数据可视化之powerBI入门(七)数据清洗中最常使用的十三招
https://mp.weixin.qq.com/s?__biz=MzA4MzQwMjY4MA==&mid=2484067158&idx=1&sn=4ad955112df2f4 ...
- Unity- 小“东西”
菜单栏遍历处理预制体工具 public class GameEditor : Editor { private static void ProcessPrefabs(Action<GameObj ...
- Xamarin.Android调用百度地图
下载百度地图API Android SDK 在Visual Studio中创建绑定库(Android)项目 将jar文件添加到Jars文件夹中 生成该项目,如果遇到变量名称之类的问题,可在Transf ...
- 使用OpenCV对图片进行特征点检测和匹配(C++)
背景 最近从不同网站下载了非常多的动漫壁纸,其中有一些内容相同,但是大小.背景颜色.色调.主人公的位置不同(例子如下).正因为如此,基础的均方误差.直方图检测等方法很难识别出这些相似的图片. 思路 O ...
- maven 将jar包添加本地仓库源
有如下jar包 zxing3.2.1.jar zxingcore.jar QRCode.jar 存在于本机目录 D:\Program Files\eclipse_workspace\webapp\We ...
- window下远程连接redis服务
首先下redis包: 下载地址:https://github.com/MSOpenTech/redis/releases. 之后: 1.注释掉redis.windows-service.conf 中的 ...
- vue-过渡动画和 第三方动画库导入,带图
vue路由过渡动画 //用transition将路由出口包裹起来 <transition name="fade" mode="out-in"> &l ...
- 01 shell编程之变量定义
一.SHELL介绍 ㈠ 什么是shell脚本? 简单来说就是将需要执行的命令保存到文本中,按照顺序执行.它是解释型的,意味着不需要编译. 若干命令 + 脚本的基本格式 + 脚本特定语法 + 思想= s ...
- Terminal终端控制台常用操作命令
新建文件夹和文件 cd .. 返回上一级 md test 新建test文件夹 md d:\test\my d盘下新建文件夹 cd test 进入test文件夹 cd.>cc.txt 新建cc.t ...