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. 可遇不可求的Question之INSERT … ON DUPLICATE KEY UPDATE 语法篇

    MySQL 自4.1版以后开始支持INSERT … ON DUPLICATE KEY UPDATE语法,使得原本需要执行3条SQL语句(SELECT,INSERT,UPDATE),缩减为1条语句即可完 ...

  2. docker install

    1.安装必要工具集 sudo yum install -y yum-utils 2.安装Docker官方源 sudo yum-config-manager \ --add-repo \ https:/ ...

  3. git的命令行操作

    1.初始化本地的git仓库git init,代码存放在这里,git会自动对我们的代码进行管理备份. 2.设置用户信息,设置用户名:git config --global user.name " ...

  4. eclipse项目无故报错,markers信息为An error occurred while filtering resources

    eclipse项目无故报错,markers信息为An error occurred while filtering resources 描述:eclipse项目和resource文件上有红色的叉,其m ...

  5. 【转载】关于.NET下开源及商业图像处理(PSD)组件

    原创]关于.NET下开源及商业图像处理(PSD)组件   阅读目录 1 前言 2 .NET图像处理组件总结 3.相关资源网址        本博客所有文章分类的总目录:http://www.cnblo ...

  6. JVM之虚拟机类加载机制

    有兴趣可以先参考前面的几篇JVM总结: JVM自动内存管理机制-Java内存区域(上) JVM自动内存管理机制-Java内存区域(下)     JVM垃圾收集器与内存分配策略(一) 我们知道,在编写一 ...

  7. HBase数据模型

    上次我们讲过了<HBase简介>,点击阅读有助于更好地理解本文.本文讲述的是HBase数据模型. 1.ROW KEY 决定一行数据按照字典顺序排序的.Row key只能存储64k的字节数据 ...

  8. Java 使用 int 数据计算百分比

    int diliverNum=3;//举例子的变量 int queryMailNum=9;//举例子的变量 // 创建一个数值格式化对象 NumberFormat numberFormat = Num ...

  9. Laravel 5.6: Specified key was too long error

    Laravel 5.6: Specified key was too long error 在Laravel执行以下命令: php artisan migrate 这是由于Laravel5.6设置了数 ...

  10. 从零开始单排学设计模式「装饰模式」黑铁 I

    阅读本文大概需要 3.6 分钟. 本篇是设计模式系列的第四篇,虽然之前也写过相应的文章,但是因为种种原因后来断掉了,而且发现之前写的内容也很渣,不够系统. 所以现在打算重写,加上距离现在也有一段时间了 ...