本文转自:https://www.cnblogs.com/aishangyipiyema/p/9262642.html

什么是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# 实现Jwt bearer Authentication的更多相关文章

  1. ASP.NET Core WebAPI中使用JWT Bearer认证和授权

    目录 为什么是 JWT Bearer 什么是 JWT JWT 的优缺点 在 WebAPI 中使用 JWT 认证 刷新 Token 使用授权 简单授权 基于固定角色的授权 基于策略的授权 自定义策略授权 ...

  2. Add JWT Bearer Authorization to Swagger and ASP.NET Core

    Add JWT Bearer Authorization to Swagger and ASP.NET Core     If you have an ASP.NET Core web applica ...

  3. 【转】ASP.NET Core WebAPI JWT Bearer 认证失败返回自定义数据 Json

    应用场景:当前我们给微信小程序提供服务接口,接口中使用了权限认证这一块,当我使用 JWT Bearer 进行接口权限认证的时候,返回的结果不是我们客户端想要的,其它我们想要给客户端返回统一的数据结构, ...

  4. FastAPI 学习之路(二十九)使用(哈希)密码和 JWT Bearer 令牌的 OAuth2

    既然我们已经有了所有的安全流程,就让我们来使用 JWT 令牌和安全哈希密码让应用程序真正地安全. 关于 JWT 它是一个将 JSON 对象编码为密集且没有空格的长字符串的标准.字符串看起来像这样: e ...

  5. [JWT] AngularJS Authentication with JWT

    Set up server for JWT Authentication 1. require express 2. require faker: If faker is not install ye ...

  6. .Net Core JWT Bearer 的认证

    关于JWT原理在这不多说,主要由三部分组成:Header.Payload.Signature,有兴趣自己上网了解. 1.首先创建.Net Core 一个Api项目 2.添加 JWT 配置 2.1 修改 ...

  7. 第29章 保护API - Identity Server 4 中文文档(v1.0.0)

    IdentityServer 默认以JWT(JSON Web令牌)格式发出访问令牌. 今天的每个相关平台都支持验证JWT令牌,这里可以找到一个很好的JWT库列表.热门库例如: ASP.NET Core ...

  8. IdentityServer4【Topic】之保护APIs

    Protecting APIs 保护api 默认情况下IdentityServer将access token发布成JWT(json web token)格式的. 现在,每个相关的平台都支持验证JWT令 ...

  9. IdentityServer4-主题

    一.Startup 二.定义Resources 三.定义Clients 四.登录 五.使用外部身份提供商登录 六.Windows身份验证 七.登出 八.注销外部身份提供商 九.联合注销 十.联合网关 ...

随机推荐

  1. linux android开发环境搭建

    android开发环境搭建的一些有用链接:1.sdk manager的国内服务器http://www.cnblogs.com/huangjacky/p/4077982.html2.常见问题的解决htt ...

  2. 日常问题181101: ueditor文本编辑器

    下载地址: https://ueditor.baidu.com/website/download.html#ueditor 把下载好的文件整个复制到根目录(或是,想要存放的目录) 引入css: < ...

  3. Nginx的虚拟主机配置

    虚拟主机技术能够让同一台服务器.同一组Nginx进程上运行多个网站,降低了资金和服务器资源的损耗.Nginx可以配置三种类型的虚拟主机,本文就是主要介绍这三种虚拟主机配置方式. 配置基于IP的虚拟主机 ...

  4. java课程课后作业190425之一维数组最大子数组(界面实现)

    题目要求: 1.在第一个问题过程中,我在以前的代码中好像已经写出了这个功能,想要实现这个功能,我们只需要在我们储存的数组和是负数的时候对中转值进行重新赋值就可以得到新的数值的起始位置,而他的终了位置就 ...

  5. mybatis3源码阅读之SqlSessionFactoryBuilder

    /** 构造器,根据配置或者代码生成SqlSessionFactory,采用分布构建的Builder模式 /* public class SqlSessionFactoryBuilder { /** ...

  6. DataRow[]

    datarow[]是datatable 的行数组集合,但是呢好像是不能直接初始化,只能是datarow[] rows = dt.select(condition);这样子.(也可能我才疏学浅没找到吧) ...

  7. 干货分享:Neutron的PPT,帮助你理解Neutron的各种细节

    深入解析Neutron http://files.cnblogs.com/popsuper1982/Neutron.pptx 经典的三节点部署 架构 怎么理解? 更加深入:Tap Interface ...

  8. python3 stack/ queue和deque模块

    '''栈stack 先进后出FILO (first in last out)'''lst = []lst.append("张一山")lst.append("杨紫" ...

  9. [Swift]LeetCode206. 反转链表 | Reverse Linked List

    Reverse a singly linked list. Example: Input: 1->2->3->4->5->NULL Output: 5->4-> ...

  10. [Swift]LeetCode705. 设计哈希集合 | Design HashSet

    Design a HashSet without using any built-in hash table libraries. To be specific, your design should ...