解码 id_token
简介
id_token是一个特殊的token,在Microsoft Graph的认证和授权过程中颁发,它包含了已认证用户的一些信息。本文将介绍如何通过实例理解id_token,并且演示了如何解码。
准备环境
本文假设你已经知道如何在Azure AD中创建应用程序注册,并且在本地创建一个最简单的网站应用程序,下面这个是用asp.net core 创建的一个例子
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;
using Microsoft.AspNetCore.Diagnostics;
using System.Text;
using System.IO;
namespace webconsole
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
}
// 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.Run(async (context) =>
{
var sb = new StringBuilder();
foreach (var item in context.Request.Query)
{
sb.AppendLine($"{item.Key}={item.Value}");
}
var reader = new StreamReader(context.Request.Body);
sb.AppendLine(reader.ReadToEnd());
await context.Response.WriteAsync(sb.ToString());
});
}
}
}
通过dotnet run命令可以将这个应用程序运行起来。
如何获取id_token
id_token是一个特殊的token,在Microsoft Graph的认证和授权过程中颁发,它包含了已认证用户的一些信息。认证的协议,我们可以统一使用OpenId Connect(实际上,这是基于OAuth 的一个简单版本),授权的协议,则是采用OAuth。
如果只是需要进行身份认证,使用OpenId Connect,但需要注意的是,这种方式主要适合在Web应用中,有用户交互的情况下,你可以通过在浏览器中输入下面的地址请求用户身份认证
完成身份认证后,正常情况下在浏览器中可以看到如下的结果
页面上已经可以看到id_token的信息。这是一串Base64编码的文本,如下所示
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IkZTaW11RnJGTm9DMHNKWEdtdjEzbk5aY2VEYyIsImtpZCI6IkZTaW11RnJGTm9DMHNKWEdtdjEzbk5aY2VEYyJ9.eyJhdWQiOiI2MTE5OTNlMi1iZjM3LTQ4OTUtODQxZC05NzM3MDc2Y2RiNDUiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC81OTcyM2Y2Yi0yZDE0LTQ5ZmUtODI3YS04ZDA0ZjlmZTdhNjgvIiwiaWF0IjoxNTIxNjk0ODg5LCJuYmYiOjE1MjE2OTQ4ODksImV4cCI6MTUyMTY5ODc4OSwiYWlvIjoiWTJOZ1lMQzlKLzYzek9JNFQzekFGYyt6ejkvRnZVMElpWjNYb1pEaXREbjQ4ZmJyRElJQSIsImFtciI6WyJwd2QiXSwiZmFtaWx5X25hbWUiOiLpmYgiLCJnaXZlbl9uYW1lIjoi5biM56ugIiwiaXBhZGRyIjoiMTY3LjIyMC4yNTUuNTIiLCJuYW1lIjoi6ZmIIOW4jOeroCIsIm5vbmNlIjoiNzM2MkNBRUEtOUNBNS00QjQzLTlCQTMtMzREN0MzMDNFQkE3Iiwib2lkIjoiMmM4ZGQxMTQtZDVjYS00Nzc0LWJmMmMtNGI1NWVmMjdkNTYwIiwic3ViIjoiMmh0QlREcEZYeHh6OTBZUHRjNzRWUkktQUoydFB6bEVwU0lSY2U3RVRUTSIsInRpZCI6IjU5NzIzZjZiLTJkMTQtNDlmZS04MjdhLThkMDRmOWZlN2E2OCIsInVuaXF1ZV9uYW1lIjoiYXJlc0BvZmZpY2UzNjVkZXZsYWJzLm9ubWljcm9zb2Z0LmNvbSIsInVwbiI6ImFyZXNAb2ZmaWNlMzY1ZGV2bGFicy5vbm1pY3Jvc29mdC5jb20iLCJ1dGkiOiJRYXJBaDNKdV9rMlp2Vko3X0o4QkFBIiwidmVyIjoiMS4wIn0.AH1PI9pUMuI9J0DNOp6LVHW3yibf-b8hD3v6dSs2Pn-eGU2fi3HOY4ZU_fGSltTiVfDL-MRRispinNuhUTh3Aa9Gw936lbVs7N6zpN_SsCxIzdzq3quYxRtHoB84eXqzs7FDy53TDXtmtr89hI9wKtV2QI2pw7rBTlhuuQOxdl0638RB-eGMCtDWVj0SvK63FafazZBWdW8YSeJjf5x2XgZoNWwArGn-U5GcyTjMSywyOXJ6Ff5HssqjzuLQCtqXTL1Ouscx-M1DUyfYN-mlwHwRd3UQgUCkPgbaDebsXaz0lGXCOC61cwfkRWGjbtVLqn6DQNDlXwvggB3MTiT1TQ
解码 id_token
你可能会说,这个id_token怎么完全看不懂呢?其实这是一个JSON的字符串,但是用Base64编码过的,而且分为三个部分(头部,声明,签名),用句点(.)分开的。
有一个最快的方法可以解码 id_token,就是通过jwt.ms 这个网站来查看用户信息
那么,如果要在我们的应用程序中进行解码,应该怎么做呢?其实正常情况下,使用下面的方式就可以实现
var id_token= "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IkZTaW11RnJGTm9DMHNKWEdtdjEzbk5aY2VEYyIsImtpZCI6IkZTaW11RnJGTm9DMHNKWEdtdjEzbk5aY2VEYyJ9.eyJhdWQiOiI2MTE5OTNlMi1iZjM3LTQ4OTUtODQxZC05NzM3MDc2Y2RiNDUiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC81OTcyM2Y2Yi0yZDE0LTQ5ZmUtODI3YS04ZDA0ZjlmZTdhNjgvIiwiaWF0IjoxNTIxNjk0ODg5LCJuYmYiOjE1MjE2OTQ4ODksImV4cCI6MTUyMTY5ODc4OSwiYWlvIjoiWTJOZ1lMQzlKLzYzek9JNFQzekFGYyt6ejkvRnZVMElpWjNYb1pEaXREbjQ4ZmJyRElJQSIsImFtciI6WyJwd2QiXSwiZmFtaWx5X25hbWUiOiLpmYgiLCJnaXZlbl9uYW1lIjoi5biM56ugIiwiaXBhZGRyIjoiMTY3LjIyMC4yNTUuNTIiLCJuYW1lIjoi6ZmIIOW4jOeroCIsIm5vbmNlIjoiNzM2MkNBRUEtOUNBNS00QjQzLTlCQTMtMzREN0MzMDNFQkE3Iiwib2lkIjoiMmM4ZGQxMTQtZDVjYS00Nzc0LWJmMmMtNGI1NWVmMjdkNTYwIiwic3ViIjoiMmh0QlREcEZYeHh6OTBZUHRjNzRWUkktQUoydFB6bEVwU0lSY2U3RVRUTSIsInRpZCI6IjU5NzIzZjZiLTJkMTQtNDlmZS04MjdhLThkMDRmOWZlN2E2OCIsInVuaXF1ZV9uYW1lIjoiYXJlc0BvZmZpY2UzNjVkZXZsYWJzLm9ubWljcm9zb2Z0LmNvbSIsInVwbiI6ImFyZXNAb2ZmaWNlMzY1ZGV2bGFicy5vbm1pY3Jvc29mdC5jb20iLCJ1dGkiOiJRYXJBaDNKdV9rMlp2Vko3X0o4QkFBIiwidmVyIjoiMS4wIn0.AH1PI9pUMuI9J0DNOp6LVHW3yibf-b8hD3v6dSs2Pn-eGU2fi3HOY4ZU_fGSltTiVfDL-MRRispinNuhUTh3Aa9Gw936lbVs7N6zpN_SsCxIzdzq3quYxRtHoB84eXqzs7FDy53TDXtmtr89hI9wKtV2QI2pw7rBTlhuuQOxdl0638RB-eGMCtDWVj0SvK63FafazZBWdW8YSeJjf5x2XgZoNWwArGn-U5GcyTjMSywyOXJ6Ff5HssqjzuLQCtqXTL1Ouscx-M1DUyfYN-mlwHwRd3UQgUCkPgbaDebsXaz0lGXCOC61cwfkRWGjbtVLqn6DQNDlXwvggB3MTiT1TQ";
var token_parts = id_token.Split('.');
var header = Encoding.UTF8.GetString(Convert.FromBase64String(token_parts[0]));
var claims = Encoding.UTF8.GetString(Convert.FromBase64String(token_parts[1]));
Console.WriteLine(header);
Console.WriteLine(claims);
但是上述代码,有时候会报错,我发现可能是用户信息中包含了中文的原因。但是可以通过一些第三方的库来实现完美的解码,例如Atom.Module.Base64Url这个package。下面是一个完整的例子:
using System;
using System.Text;
using Atom.Toolbox;
namespace ConsoleApp4
{
class Program
{
static void Main(string[] args)
{
var id_token= "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IkZTaW11RnJGTm9DMHNKWEdtdjEzbk5aY2VEYyIsImtpZCI6IkZTaW11RnJGTm9DMHNKWEdtdjEzbk5aY2VEYyJ9.eyJhdWQiOiI2MTE5OTNlMi1iZjM3LTQ4OTUtODQxZC05NzM3MDc2Y2RiNDUiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC81OTcyM2Y2Yi0yZDE0LTQ5ZmUtODI3YS04ZDA0ZjlmZTdhNjgvIiwiaWF0IjoxNTIxNjk0ODg5LCJuYmYiOjE1MjE2OTQ4ODksImV4cCI6MTUyMTY5ODc4OSwiYWlvIjoiWTJOZ1lMQzlKLzYzek9JNFQzekFGYyt6ejkvRnZVMElpWjNYb1pEaXREbjQ4ZmJyRElJQSIsImFtciI6WyJwd2QiXSwiZmFtaWx5X25hbWUiOiLpmYgiLCJnaXZlbl9uYW1lIjoi5biM56ugIiwiaXBhZGRyIjoiMTY3LjIyMC4yNTUuNTIiLCJuYW1lIjoi6ZmIIOW4jOeroCIsIm5vbmNlIjoiNzM2MkNBRUEtOUNBNS00QjQzLTlCQTMtMzREN0MzMDNFQkE3Iiwib2lkIjoiMmM4ZGQxMTQtZDVjYS00Nzc0LWJmMmMtNGI1NWVmMjdkNTYwIiwic3ViIjoiMmh0QlREcEZYeHh6OTBZUHRjNzRWUkktQUoydFB6bEVwU0lSY2U3RVRUTSIsInRpZCI6IjU5NzIzZjZiLTJkMTQtNDlmZS04MjdhLThkMDRmOWZlN2E2OCIsInVuaXF1ZV9uYW1lIjoiYXJlc0BvZmZpY2UzNjVkZXZsYWJzLm9ubWljcm9zb2Z0LmNvbSIsInVwbiI6ImFyZXNAb2ZmaWNlMzY1ZGV2bGFicy5vbm1pY3Jvc29mdC5jb20iLCJ1dGkiOiJRYXJBaDNKdV9rMlp2Vko3X0o4QkFBIiwidmVyIjoiMS4wIn0.AH1PI9pUMuI9J0DNOp6LVHW3yibf-b8hD3v6dSs2Pn-eGU2fi3HOY4ZU_fGSltTiVfDL-MRRispinNuhUTh3Aa9Gw936lbVs7N6zpN_SsCxIzdzq3quYxRtHoB84eXqzs7FDy53TDXtmtr89hI9wKtV2QI2pw7rBTlhuuQOxdl0638RB-eGMCtDWVj0SvK63FafazZBWdW8YSeJjf5x2XgZoNWwArGn-U5GcyTjMSywyOXJ6Ff5HssqjzuLQCtqXTL1Ouscx-M1DUyfYN-mlwHwRd3UQgUCkPgbaDebsXaz0lGXCOC61cwfkRWGjbtVLqn6DQNDlXwvggB3MTiT1TQ";
var token_parts = id_token.Split('.');
var header = Encoding.UTF8.GetString(Base64Url.Decode(token_parts[0]));
var claims = Encoding.UTF8.GetString(Base64Url.Decode(token_parts[1]));
Console.WriteLine(header);
Console.WriteLine(claims);
Console.Read();
}
}
}

解码 id_token的更多相关文章
- linux字符串url编码与解码
编码的两种方式 echo '手机' | tr -d '\n' | xxd -plain | sed 's/\(..\)/%\1/g' echo '手机' |tr -d '\n' |od -An -tx ...
- URI编码解码和base64
概述 对于uri的编解码,在js中有3对函数,分别是escape/unescape,encodeURI/decodeURI,encodeURIComponent/decodeURIComponent. ...
- FFmpeg学习2:解码数据结构及函数总结
在上一篇文章中,对FFmpeg的视频解码过程做了一个总结.由于才接触FFmpeg,还是挺陌生的,这里就解码过程再做一个总结. 本文的总结分为以下两个部分: 数据读取,主要关注在解码过程中所用到的FFm ...
- Unicode转义(\uXXXX)的编码和解码
在涉及Web前端开发时, 有时会遇到\uXXXX格式表示的字符, 其中XXXX是16进制数字的字符串表示形式, 在js中这个叫Unicode转义字符, 和\n \r同属于转义字符. 在其他语言中也有类 ...
- C# base 64图片编码解码
使用WinForm实现了图片base64编码解码的 效果图: 示例base 64编码字符串: /9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKD ...
- java编码原理,java编码和解码问题
java的编码方式原理 java的JVM的缺省编码方式由系统的“本地语言环境”设置确定,和操作系统的类型无关 . 在JAVA源文件-->JAVAC-->Class-->Java--& ...
- [LeetCode] Decode String 解码字符串
Given an encoded string, return it's decoded string. The encoding rule is: k[encoded_string], where ...
- [LeetCode] Encode and Decode Strings 加码解码字符串
Design an algorithm to encode a list of strings to a string. The encoded string is then sent over th ...
- [LeetCode] Decode Ways 解码方法
A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' - ...
随机推荐
- 'An instance 0x155e74a0 of class UIWebView was deallocated while key value observers were still registered with it.
在iOS和html混编的时候,当用iOS原生的navigation导航pop回去的时候,出现 *** Terminating app due to uncaught exception 'NSInte ...
- Python编程练习:简单的闹钟提醒
问题详情:当前时间为下午2点,你在手机上设置了一个闹钟提醒,10000秒后触发该闹钟,请问闹钟铃声响起时的具体时间?请用print打印出时间 源码: a = 10000 h,m,s=2,0,0 if ...
- 40个Java多线程面试问题
1. 多线程有什么用? 一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用?在我看来,这个回答更扯淡.所谓"知其然知其所以然","会用"只 ...
- 在谷歌安装扩展程序Axure RP Extension for Chrome后,经常无故损坏,无法使用
最近因为要看需求给的原型图,但需求只给了html格式的文件,没有给可以在Axure软件里看的格式, 所以在谷歌安装了一个Axure RP Extension for Chrome扩展程序在谷歌浏览器看 ...
- SpringMVC框架一:搭建测试
这里做一个Demo:展示商品列表 新建Dynamic Web Project: 导入jar包,放在lib下: 放入Lib文件夹之后,会自动build path 接下来配置web.xml: <?x ...
- iview导航菜单updateOpened和updateActiveName的使用
先看官方文档: iview导航菜单 这里主要遇到的问题有两个: 1. 点击回到首页(B按钮)时需要取消选中当前选中的菜单项(全部不选中),这里用到的是 updateActiveName方法 2. 点击 ...
- 原生JS实现弹幕效果
纯属无聊写的,可能有很多问题,欢迎批评指教. 效果图:图一是预设的一些弹幕,图二是自己发射的弹幕,效果是一样的. 首先是弹幕的位置,是要从最右滑到最左,为了防止随机高度弹幕会覆盖的问题,设置了通道 ...
- Ubuntu下将python从2.7升级到3.5
在ubuntu 的终端中用代码下载最新的Python sudo apt-get install python3 系统会提示输入Linux 的密码,输入密码后下载 刚才下载的Python程序被安装在us ...
- HPE服务器做raid5阵列
HPE服务器做阵列的详细步骤: 注意:HPE服务器加硬盘需要安装配套的扩展笼~~~ 1.首先服务器开机,出现下图界面按F10. 2.然后在下图中选择HPE interlligent Provision ...
- mysql 开发进阶篇系列 42 逻辑备份与恢复(mysqldump 的完全恢复)
一.概述 在作何数据库里,备份与恢复都是非常重要的.好的备份方法和备份策略将会使得数据库中的数据更加高效和安全.对于DBA来说,进行备份或恢复操作时要考虑的因素大概有如下: (1) 确定要备份的表的存 ...