Jwtbearer Authentication

什么是JWT

JWT(JSON Web Token), 顾名思义就是在Web上以JSON格式传输的Token(RFC 7519)。

该Token被设计为紧凑声明表示格式,特别适用于分布式站点的单点登录(SSO)场景。

紧凑 :意味着size小,所以可以在URL中,Header中,Post Parameter中进行传输,并且包含了所需要的信息。

JWT的构成

JWT一般由三段构成,用"."号分隔开

Header.Payload.Signature

例如:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

点击链接 如下图

图左边为Header.Payload.Signature的base64编码

图右构成

Header

  • alg:声明加密的算法 ,这里为HS256
  • typ:声明类型,这里为JWT

然后将Header进行base64编码 得到第一部分

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

Payload

由三部分构成

  • 标准中注册的声明

  • 公共的声明

  • 私有的声明

    标准中注册的声明 (建议但不强制使用) :

    • iss: jwt签发者

    • sub: jwt所面向的用户

    • aud: 接收jwt的一方

    • exp: jwt的过期时间,这个过期时间必须要大于签发时间

    • nbf: 定义在什么时间之前,该jwt都是不可用的.

    • iat: jwt的签发时间

    • jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

    公共的声明 :

公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密.

私有的声明 :

私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base6编码可以归类为明文信息 。

定义一个payload:

{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}

然后将其进行base64加密,得到Jwt的第二部分。

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

Signature(数字签名,防止信息被篡改)

jwt的第三部分是一个签证信息,这个签证信息由三部分组成:

  • Header (base64后的)

  • Payload (base64后的)

  • Secret

    这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分 。

    // javascript
    var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
    var signature = HMACSHA256(encodedString, 'secret');

    将这三部分用.连接成一个完整的字符串,构成了最终的jwt:

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

    注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。

下面我们自己来实现一下 JwtBearer Authentication

  1. 新建一个WebApi项目

  1. 新建JwtSeetings类

        public class JwtSeetings
    {
    /// <summary>
    /// 谁颁发的jwt
    /// </summary>
    public string Issuer { get; set; } /// <summary>
    /// 谁使用这个jwt
    /// </summary>
    public string Audience { get; set; } /// <summary>
    /// secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,
    /// 所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了
    /// 通过jwt header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分
    /// </summary>
    public string SecretKey { get; set; }
    }
  2. appsettings.json里面配置如下

    "JwtSeetings": {
    "Issuer": "http://localhost:5000",
    "Audience": "http://localhost:5000",
    "SecretKey": "zhoudafu201807041123"
  3. Startup类里面ConfigureServices添加如下代码

        services.Configure<JwtSeetings>(Configuration.GetSection("JwtSeetings"));
    
                var jwtSeetings = new JwtSeetings();
    //绑定jwtSeetings
    Configuration.Bind("JwtSeetings", jwtSeetings);
    services.AddAuthentication(options =>
    {
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; })
    .AddJwtBearer(options =>
    {
    options.TokenValidationParameters = new TokenValidationParameters
    {
    ValidIssuer = jwtSeetings.Issuer,
    ValidAudience = jwtSeetings.Audience,
    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSeetings.SecretKey))
    };
    })
    ;
  4. Startup类里面Configure添加如下代码

     app.UseAuthentication();
  5. 新增AuthroizeController控制器,并添加如下代码

    [HttpPost]
    public ActionResult Post([FromBody]LoginViewModel loginViewModel)
    { if (!ModelState.IsValid)
    {
    return BadRequest();
    }
    if (loginViewModel.Name == "jack" && loginViewModel.Password == "rose")
    { var claims = new Claim[]
    {
    new Claim(ClaimTypes.Name,"jack"),
    new Claim(ClaimTypes.Role,"admin")
    };
    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSeetings.SecretKey));
    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken(
    _jwtSeetings.Issuer,
    _jwtSeetings.Audience,
    claims,
    DateTime.Now,
    DateTime.Now.AddMinutes(30),
    creds
    );
    return Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token) });
    } return BadRequest();
    }
  6. 给ValuesController控制器打上[Authorize]特性

  7. 用Postman直接访问http://localhost:5000/api/Values 返回401

  8. 用Postman访问http://localhost:5000/api/Authroize 得到Token

  9. 通过Bearer访问成功

源代码 https://github.com/HisKingdom/JwtAuthSample

参考博客:https://www.jianshu.com/p/576dbf44b2ae

C# 实现Jwtbearer Authentication的更多相关文章

  1. 任务36:应用Jwtbearer Authentication

    任务36:应用Jwtbearer Authentication D:\MyDemos\jesse 新建项目:dotnet new webapi --name JwtAuthSample VS2017运 ...

  2. 【ASP.NET Core快速入门】(十一)应用Jwtbearer Authentication、生成jwt token

    准备工作 用VSCode新建webapi项目JwtAuthSample,并打开所在文件夹项目 dotnet new webapi --name JwtAuthSample 编辑JwtAuthSampl ...

  3. 菜鸟入门【ASP.NET Core】11:应用Jwtbearer Authentication、生成jwt token

    准备工作 用VSCode新建webapi项目JwtAuthSample,并打开所在文件夹项目 dotnet new webapi --name JwtAuthSample 编辑JwtAuthSampl ...

  4. 36-应用Jwtbearer Authentication

    新建.net core webapi项目 E:\coding\netcore>dotnet new webapi --name JwtAuthSample 创建需要用到的实体对象类 namesp ...

  5. Nancy基于JwtBearer认证的使用与实现

    前言 最近在看JSON Web Token(Jwt)相关的东西,但是发现在Nancy中直接使用Jwt的组件比较缺乏,所以就在空闲时间写了一个. 这个组件是开源的,不过目前只支持.NET Core,后续 ...

  6. [转]C# 实现Jwt bearer Authentication

    本文转自:https://www.cnblogs.com/aishangyipiyema/p/9262642.html 什么是JWT JWT(JSON Web Token), 顾名思义就是在Web上以 ...

  7. ASP.NET Core集成现有系统认证

    我们现在大多数转向ASP.NET Core来使用开发的团队,应该都不是从0开始搭建系统,而是老的业务系统已经在运行,ASP.NET Core用来开发新模块.那么解决用户认证的问题,成为我们的第一个拦路 ...

  8. 极简版ASP.NET Core学习路径及教程

    绝承认这是一个七天速成教程,即使有这个效果,我也不愿意接受这个名字.嗯. 这个路径分为两块: 实践入门 理论延伸 有了ASP.NET以及C#的知识以及项目经验,我们几乎可以不再需要了解任何新的知识就开 ...

  9. asp.net core WebAPI学习以及 发布(***入门学习)

    A asp.net Core 系列[一]——创建Web应用 asp.net Core 系列[二]—— 使用 ASP.NET Core 和 VS2017 for Windows 创建 Web API a ...

随机推荐

  1. 【Android开源库】 PagerSlidingTabStrip从头到脚

    简介 PagerSlidingTabStrip,是我个人经常使用到的一个和ViewPager配合的页面指示器,可以满足开发过程中常用的需求,如类似于今日头条的首页新闻内容导航栏等等,之前自己开发的Ju ...

  2. Debian 8.x / Ubuntu 16.04.x 搭建 Ghost 教程

    Ghost 是一款使用 Node.js 开发的博客系统,相对于使用 PHP 开发的 WordPress 更轻巧友好,所以本站已经从 WordPress 切换至 Ghost,本文介绍在 Debian 8 ...

  3. Ubuntu英文变为中文

    Ubuntu英文变为中文 注:(我也是第一次变语言,写的有点乱,我把重点的用红字表示.)     1.点击这个软件更新.  2.只有点击了上面那一步,这里才会软件资源 Software Sources ...

  4. iOS 数据归档----温故而知新

    #import "StudyViewController.h" #import "person.h" @interface StudyViewControlle ...

  5. 虚拟机Linux不能上网简单有效的解决办法

    对于刚开始接触Linux系统的用户来说,先使用虚拟机Linux学习是不错的选择.但是在用虚拟机上网的时候,总是出现这样那样的错误,到底该怎么办呢?本文笔者和大家分享一下虚拟机Linux不能上网的简单有 ...

  6. eclipse 工作区空格和回车键显示为乱码

    eclipse 工作区空格和回车键显示为乱码 解决方法:Windows => Preferences => General =>Editors =>Text Editor =& ...

  7. 疑难杂症:Java中Scanner连续获取int和String型发生错误.

    使用Scanner类获取输入,连续获取int类型和String类型数据时候,发生错误. Scanner sc = new Scanner(System.in); System.out.println( ...

  8. Python学习笔记-基础2

    1.列表list 列表是最常用的Python数据类型,它可以作为一个方括号内的逗号分隔值出现. 1.定义列表 names = ["Ronaldo","Messi" ...

  9. 为什么使用 Spring Boot?

    Spring 是一个非常流行的基于Java语言的开发框架,此框架用来构建web和企业应用程序.与许多其他仅关注一个领域的框架不同,Spring框架提供了广泛的功能,通过其组合项目满足现代业务需求. S ...

  10. Javascript高级编程学习笔记(68)—— 事件(12)设备事件

    设备事件 随着智能手机与平板电脑的普及,为了更好地让用户与这些设备进行交互 浏览器引入了一种新的方式,而一类新的事件也应运而生,这就是设备事件 W3C从2011年开始制定关于设备事件的草案 下面将会介 ...