[置顶] 【ASP.NET Core学习】使用JWT认证授权

demo地址:https://github.com/william0705/JWTS

名词解析

认证 : 识别用户是否合法

授权: 赋予用户权限 (能访问哪些资源)

鉴权: 鉴定权限是否合法

Jwt优势与劣势

优势

1、无状态

  token 存储身份验证所有信息 , 服务端不需要保存用户身份验证信息, 减少服务端压力 , 服务端更容易水平扩展, 由于无状态, 又会导致它最大缺点 , 很难注销

2、支持跨域访问

  Cookie是不允许垮域访问的,token支持

3、跨语言

  基于标准化的 JSON Web Token (JWT) , 不依赖特定某一个语言 , 例如生成的Token可以对多种语言使用(Net , Java , PHP …)

劣势

1、Token有效性问题

  后台很难注销已经发布的Token , 通常需要借助第三方储存(数据库/缓存) 实现注销, 这样就会失去JWT最大的优势

2、占带宽

  Token长度(取决存放内容) 比session_id大 , 每次请求多消耗带宽 , token只存必要信息 , 避免token过长

3、需要实现续签

  cookies – session 通常是框架已经实现续签功能, 每次访问把过期时间更新, JWT需要自己实现, 参考OAuth2刷新Token机制实现刷新Token

4、消耗更多CPU

  每次请求需要对内容解密和验证签名这两步操作,典型用时间换空间

 

只能根据自身使用场景决定使用哪一种身份验证方案 , 没有一种方案是通用的,完美的

 

.NET Core集成JWT认证授权服务

  1、认证服务API:认证用户,并发布Token

1、引入nuget包,System.IdentityModel.Tokens.Jwt
2、创建生成Token的服务,建议使用面向接口和实现编程,方便服务注入容器ServicesCollection(涉及DI和IOC概念)
3、创建接口
namespace JWTS.Services
{
    public interface IJWTService
    {
        /// <summary>
        /// 根据验证通过后的用户以及角色生成Token,以达到角色控制的作用
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="role"></param>
        /// <returns></returns>
        string GetToken(string userName,string role);
    }
}

4、在appsettings.config中添加生成token需要的信息,并映射成对象

"TokenParameter": {
    "Issuer": "William", //这个JWT的签发主体(发行者)
    "Audience": "William", //这个JWT的接收对象
    "SecurityKey": "askalsnlkndhasnaslkasmadka"
  } 

  public class TokenParameter
  {
    public string Issuer { get; set; }
    public string Audience { get; set; }
    public string SecurityKey { get; set; }
  }

5、实现接口,注入Configuration,获取TokenParameter对象

using Microsoft.Extensions.Configuration;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;

namespace JWTS.Services
{
    public class JWTService : IJWTService
    {
        private readonly TokenParameter _tokenParameter;

      public JWTService(IConfiguration configuration)
      {
        _tokenParameter = configuration.GetSection("TokenParameter").Get<TokenParameter>();
      }

     /// <summary>
        /// JWT由三部分组成(Header、Payload、Signature)
        /// {Header}.{Payload}.{Signature}
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="role"></param>
        /// <returns></returns>
        public string GetToken(string userName,string role)
        {
            Claim[] claims = new[]
            {
                new Claim(ClaimTypes.Name, userName),
                new Claim("NickName","Richard"),
                new Claim("Role",role)//传递其他信息
            };
            SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenParameter.SecurityKey));
            SigningCredentials creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            /**
             *  Claims (Payload)
                Claims 部分包含了一些跟这个 token 有关的重要信息。 JWT 标准规定了一些字段,下面节选一些字段:
                JWT会被加密,但是这部分内容任何人都可以读取,所以不要存放机密信息

                iss: The issuer of the token,token 是给谁的
                sub: The subject of the token,token 主题
                exp: Expiration Time。 token 过期时间,Unix 时间戳格式
                iat: Issued At。 token 创建时间, Unix 时间戳格式
                jti: JWT ID。针对当前 token 的唯一标识
                除了规定的字段外,可以包含其他任何 JSON 兼容的字段。
             * */
            var token = new JwtSecurityToken(
                issuer: _tokenParameter.Issuer,
                audience: _tokenParameter.Audience,
                claims: claims,
                expires: DateTime.Now.AddMinutes(10),//10分钟有效期
                signingCredentials: creds);
            string returnToken = new JwtSecurityTokenHandler().WriteToken(token);
            return returnToken;
        }
    }
}
6、jwt中定义好的Claims

JWT标准里面定好的claim有:

  • iss(Issuser):代表这个JWT的签发主体;
  • sub(Subject):代表这个JWT的主体,即它的所有人;
  • aud(Audience):代表这个JWT的接收对象;
  • exp(Expiration time):是一个时间戳,代表这个JWT的过期时间;
  • nbf(Not Before):是一个时间戳,代表这个JWT生效的开始时间,意味着在这个时间之前验证JWT是会失败的;
  • iat(Issued at):是一个时间戳,代表这个JWT的签发时间;
  • jti(JWT ID):是JWT的唯一标识。

7、在鉴权项目工程Startup.cs文件里依赖注入JWT的服务类

 public void ConfigureServices(IServiceCollection services) { services.AddScoped<IJWTService, JWTService>(); services.AddControllers(); } 

8、添加AuthenticationController,生成Token,后期可以添加RefreshToken

using JWTS.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace JWTS.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class AuthenticationController : ControllerBase
    {
        #region 构造函数
        private ILogger<AuthenticationController> _logger;
        private IJWTService _iJWTService;
        private readonly IConfiguration _iConfiguration;
        public AuthenticationController(ILogger<AuthenticationController> logger,
            IConfiguration configuration
            , IJWTService service)
        {
            _logger = logger;
            _iConfiguration = configuration;
            _iJWTService = service;
        }
        #endregion

        /// <summary>
        /// 实际场景使用Post方法
        /// http://localhost:5000/api/Authentication/Login?name=william&password=123123
        /// </summary>
        /// <param name="name"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        [Route("Login")]
        [HttpGet]
        public IActionResult Login(string name, string password)
        {
            //这里应该是需要去连接数据库做数据校验,为了方便所有用户名和密码写死了
            if ("william".Equals(name) && "123123".Equals(password))//应该数据库
            {
                var role = "Administrator";//可以从数据库获取角色
                string token = this._iJWTService.GetToken(name, role);
                return new JsonResult(new
                {
                    result = true,
                    token
                });
            }

            return Unauthorized("Not Register!!!");
        }
    }
}

2、资源中心API:使用从认证服务中心获取的Token,去访问资源,资源中心对用户信息以及Token进行鉴权操作,认证失败返回401

1、资源中心添加Nuget包(Microsoft.AspNetCore.Authentication.JwtBearer)

2、添加Authentication服务,添加JwtBearer,通过Configuration获取TokenParameter对象

using System;
using System.Text;
using API.Core.Models;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Tokens;

namespace API.Core
{
    public class Startup
    {
        private TokenParameter _tokenParameter;
        public IConfiguration Configuration { get; }
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
            _tokenParameter = configuration.GetSection("TokenParameter").Get<TokenParameter>()??throw new ArgumentNullException(nameof(_tokenParameter));
        }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)//默认授权机制
                .AddJwtBearer(options =>
                {
                    options.TokenValidationParameters=new TokenValidationParameters()
                    {
                        ValidateIssuer = true,
                        ValidateAudience = true,
                        ValidateLifetime = true,
                        ValidateIssuerSigningKey = true,
                        ValidIssuer = _tokenParameter.Issuer,
                        ValidAudience = _tokenParameter.Audience,
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenParameter.SecurityKey))
                    };
                });
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();
            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

3、在资源控制器上添加[Authorize]属性,以启用认证授权访问API资源

   [ApiController]
    [Route("[controller]")]
    [Authorize]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }

 

posted @ 2020-11-04 17:32 菜鸟客栈 阅读(868) 评论(0) 推荐(1) 编辑

[置顶] 阿里云pdf附件已文件流的形式上传、下载

只有注册用户登录后才能阅读该文。 阅读全文

posted @ 2017-12-18 13:21 菜鸟客栈 阅读(19) 评论(0) 推荐(0) 编辑

[置顶] 阿里云Oss 图片上传预览、图片上传、图片查看

只有注册用户登录后才能阅读该文。 阅读全文

posted @ 2017-12-18 13:17 菜鸟客栈 阅读(17) 评论(0) 推荐(0) 编辑

2020年11月25日

数据访问仓储模式的事务管理(Unit of Work)

摘要: 原创https://blog.csdn.net/huanghuangtongxue/article/details/79215136 1、定义IUnitOfWork接口 public interface IUnitOfWork { /// <summary> /// 提交更改 /// </summa 阅读全文

posted @ 2020-11-25 11:33 菜鸟客栈 阅读(373) 评论(0) 推荐(0) 编辑

2018年12月28日

学习计划

摘要: 1、依赖注入DI { 三种注入方式 三种生命周期 } 2、AutoMapper 3、Fluent API https://docs.microsoft.com/en-us/ef/core/modeling/ 4、.net core api 5、.net core mvc 6、Nlog(记录日志)nlog.extensions.logging等等(这里其他的日志记录组件的使用基本一致)、 http... 阅读全文

posted @ 2018-12-28 11:23 菜鸟客栈 阅读(192) 评论(1) 推荐(0) 编辑

jquery自动完成插件的使用

摘要: .ui-autocomplete { z-index:99999 !important; max-height: 100px; overflow-y: auto; /* 防止水平滚动条 */ overflow-x: hidden; z-index:9999999 } $("#Calib... 阅读全文

posted @ 2018-12-28 11:15 菜鸟客栈 阅读(162) 评论(0) 推荐(0) 编辑

2018年3月15日

文档控件NTKO OFFICE 详细使用说明之预览Excel文件(查看、编辑、保存回服务器)

摘要: 1、在线预览Excel文件 (1) 运行环境 ① 浏览器:支持IE7-IE11(平台版本还支持Chrome和Firefox) ② IE工具栏-Internet 选项:将www.ntko.com加入到浏览器的可信站点中,不启用保护模式,并将HTTPS验证取消 ③ 如果是开发人员首次使用文档控件,需要将 阅读全文

posted @ 2018-03-15 09:44 菜鸟客栈 阅读(3069) 评论(0) 推荐(0) 编辑

文档控件NTKO OFFICE 详细使用说明之预览word编辑保存回服务器

摘要: 1、在线预览Word文件 (1) 运行环境 ① 浏览器:支持IE7-IE11(平台版本还支持Chrome和Firefox) ② IE工具栏-Internet 选项:将www.ntko.com加入到浏览器的可信站点中,不启用保护模式,并将HTTPS验证取消 ③ 如果是开发人员首次使用文档控件,需要将控 阅读全文

posted @ 2018-03-15 09:42 菜鸟客栈 阅读(6700) 评论(0) 推荐(0) 编辑

文档控件NTKO OFFICE 详细使用说明之预览PDF文件(禁止打印、下载、另存为、防抓包下载)

摘要: 1、在线预览PDF文件(禁止打印、下载、复制、另存为) (1) 运行环境 ① 浏览器:支持IE7-IE11(平台版本还支持Chrome和Firefox) ② IE工具栏-Internet 选项:将www.ntko.com加入到浏览器的可信站点中,不启用保护模式,并将HTTPS验证取消 ③ 如果是开发 阅读全文

posted @ 2018-03-15 09:22 菜鸟客栈 阅读(6662) 评论(0) 推荐(0) 编辑

Devexpress PdfViewer预览pdf,禁止下载,打印,复制

摘要: PDFviewer控件: 参数设置: 1、屏蔽书签栏和右键菜单 2、加载文档支持路径以及流stream加载的方式 文件保存路径对话框: pdf文件下载: pdf打印: 阅读全文

posted @ 2018-03-15 09:10 菜鸟客栈 阅读(1511) 评论(0) 推荐(0) 编辑

2018年2月26日

异步方法

摘要: 阅读全文

posted @ 2018-02-26 16:41 菜鸟客栈 阅读(139) 评论(0) 推荐(0) 编辑

2018年2月9日

JsonResult

摘要: 注意:如果有大量的json数据要处理,建议使用ASP .NET Web API框架处理,专门用来处理json数据交换并提供跨平台访问能力的 ConentType设置为application/json 使用JSonResult时,默认不允许HTTPGET请求 return Json(product,J 阅读全文

posted @ 2018-02-09 11:19 菜鸟客栈 阅读(500) 评论(0) 推荐(0) 编辑

JavaScriptResult

摘要: 阅读全文

posted @ 2018-02-09 10:58 菜鸟客栈 阅读(250) 评论(0) 推荐(0) 编辑

ModelState对象

摘要: 1、在控制器中判断Model验证结果 阅读全文

posted @ 2018-02-09 10:31 菜鸟客栈 阅读(212) 评论(0) 推荐(0) 编辑

字段属性验证规则

摘要: 阅读全文

posted @ 2018-02-09 10:09 菜鸟客栈 阅读(643) 评论(0) 推荐(0) 编辑

2018年1月30日

DropDownListFor

摘要: 阅读全文

posted @ 2018-01-30 10:01 菜鸟客栈 阅读(140) 评论(0) 推荐(0) 编辑

2018年1月18日

异步lambda表达式

摘要: 阅读全文

posted @ 2018-01-18 10:40 菜鸟客栈 阅读(726) 评论(0) 推荐(0) 编辑

2018年1月17日

扩展方法

摘要: 例如:扩展int方法 声明完扩展方法后,在vs中会自动侦测,直接调用即可 int i=100; i.FormatForMoney(); 若要引用不同命名空间类的扩展方法,记得加上using引用,否则编译器无法找到扩展方法 阅读全文

posted @ 2018-01-17 15:57 菜鸟客栈 阅读(106) 评论(0) 推荐(0) 编辑

2018年1月12日

winFrom线程

摘要: 方法 》委托 》BeginInvoke用指定的参数异步执行委托 委托就是我想做什么,而你可以作什么,我就让你去做。 阅读全文

posted @ 2018-01-12 17:14 菜鸟客栈 阅读(104) 评论(0) 推荐(0) 编辑

2018年1月4日

king枚举帮助类

摘要: 可以方便的实现枚举 阅读全文

posted @ 2018-01-04 14:46 菜鸟客栈 阅读(121) 评论(0) 推荐(0) 编辑

2017年12月29日

Get/Post请求

摘要: 通常情况下,GET请求用于读操作,POST请求用于写操作(通常包括更新、创建和删除) http://www.cnblogs.com/tangge/p/6230757.html#t0 1 public static class RequestHelper 2 { 3 private static re 阅读全文

posted @ 2017-12-29 10:51 菜鸟客栈 阅读(182) 评论(0) 推荐(0) 编辑

2017年12月22日

MVC Remote属性验证

摘要: 模型验证方式一: 1、需要添加引用: using System.Web.Mvc; 2、在模型属性上添加验证: [Remote("CheckIsHaveSerialNo", "MeasureEquipment",ErrorMessage = "出厂编号已存在")] 3、在控制器里面添加验证方法: 模型 阅读全文

posted @ 2017-12-22 14:09 菜鸟客栈 阅读(1257) 评论(0) 推荐(0) 编辑

2017年12月21日

随笔2017/12/21

摘要: /** * 把byte[]数组的内容写到文件里面,文件名字叫做flash.swf。 * 位置在getCacheDir这个目录/data/data/包名/cache里面 * * @param swfByte * byte数组 * */ public void byte2File(byte[] swfB 阅读全文

posted @ 2017-12-21 11:03 菜鸟客栈 阅读(153) 评论(0) 推荐(0) 编辑

2017年12月20日

sql批量更新数据

摘要: update 表1 SET 表1.CnasDate=t1.日期 FROM (select 日期,Id from 表2) as t1 left join 表1 as t2 ON t1.Id=t2.ID 更简洁的写法(推荐) update 表一 set 表一的字段= 表2的字段 from 表一, 表二 where 表一.Id = 表二.BranchI... 阅读全文

posted @ 2017-12-20 16:12 菜鸟客栈 阅读(11885) 评论(0) 推荐(0) 编辑

dapper

摘要: select count(1) from Sys_Admin where 1=1 工具类 查询的In操作: 阅读全文

posted @ 2017-12-20 14:30 菜鸟客栈 阅读(387) 评论(0) 推荐(0) 编辑

项目代码风格要求

摘要: https://kb.cnblogs.com/page/179593/ 阅读全文

posted @ 2017-12-20 14:15 菜鸟客栈 阅读(115) 评论(0) 推荐(0) 编辑

页面间传值

摘要: ViewBag.Url >页面1,传值到页面1,页面1提交时可以直接使用 绝对路径:Url=Request.Url.Request.Url.AbsoluteUri 阅读全文

posted @ 2017-12-20 11:50 菜鸟客栈 阅读(103) 评论(0) 推荐(0) 编辑

2017年12月19日

WebApi使用swagger ui自动生成接口文档

摘要: http://www.cnblogs.com/EvanWay/p/7755992.html 阅读全文

posted @ 2017-12-19 16:33 菜鸟客栈 阅读(136) 评论(0) 推荐(0) 编辑

生成二维码

摘要: https://www.cnblogs.com/jys509/p/4592539.html 阅读全文

posted @ 2017-12-19 16:30 菜鸟客栈 阅读(86) 评论(0) 推荐(0) 编辑

文件操作:Directory,File,FielStream、StreamRead和StreamWriter的使用

摘要: Directory文件类,File,FielStream、StreamRead和StreamWriter的使用 (转载) 创建一个新文件 Directory.CreateDirectory(@"C: \Users\enle\Desktop\new");//路径 删除一个文件 Directory.De 阅读全文

posted @ 2017-12-19 16:20 菜鸟客栈 阅读(313) 评论(0) 推荐(0) 编辑

MVC中Excel导入

摘要: 1.在项目中添加对NPOI的引用,NPOI下载地址:http://npoi.codeplex.com/releases/view/38113、 前端代码 控制器 业务逻辑层 FooterDAL将datatable,就是excel里面的数据添加到sql数据库 阅读全文

posted @ 2017-12-19 16:07 菜鸟客栈 阅读(2210) 评论(1) 推荐(0) 编辑

T对象序列化后T对象中属性字段不见了?

摘要: http://blog.csdn.net/adenfeng/article/details/41622255 阅读全文

posted @ 2017-12-19 14:20 菜鸟客栈 阅读(519) 评论(0) 推荐(0) 编辑

Sql游标

摘要: 数据一条一条处理 阅读全文

posted @ 2017-12-19 08:38 菜鸟客栈 阅读(77) 评论(0) 推荐(0) 编辑

2017年12月11日

Form表单提交

摘要: http://www.cnblogs.com/CKExp/p/7895353.html(转载) 【1】、纯form表单形式,无js和ajax ,提交路径有action决定,方式由method决定,如果需要传输文件加上enctype 我的表单内容:两个下拉选择、一个文件选择和一个输入框 1 <form 阅读全文

posted @ 2017-12-11 17:26 菜鸟客栈 阅读(249) 评论(0) 推荐(0) 编辑

附件上传

该文被密码保护。 阅读全文

posted @ 2017-12-11 17:25 菜鸟客栈 阅读(3) 评论(0) 推荐(0) 编辑

AJAX异步删除操作

摘要: 1 @Ajax.ActionLink("删除", "Delete", new {id = user.Id}, ajaxOption) 2 @{ 3 var ajaxOption = new AjaxOptions() 4 { 5 OnSuccess = "DeleteSuccess", 6 OnFailure = "DeleteFail... 阅读全文

posted @ 2017-12-11 17:16 菜鸟客栈 阅读(562) 评论(0) 推荐(0) 编辑

数据库表结构导出sql语句

摘要: 在“对象资源管理器”中找到要导出的表,选中该表并单击右键,“编写表脚本为(S)”/“CREATE到(C)”/“新查询编辑器窗口”即可查看该表的建表语句,Ctrl+S保存为sql脚本文件 阅读全文

posted @ 2017-12-11 17:15 菜鸟客栈 阅读(546) 评论(0) 推荐(0) 编辑

多线程的使用

摘要: 1、开始一个线程:实例化一个线程,并将要调用的方法传给构造函数,然后调用线程对象的start方法开启一个线程 System.Threading.Thread thread=new System.Threading.Thread(Show); Thread.start(); 2、结束一个线程: if( 阅读全文

posted @ 2017-12-11 17:14 菜鸟客栈 阅读(174) 评论(0) 推荐(0) 编辑

找不到dll原因

摘要: 1、没有生成成功: A.代码有错误 B.引用dll有问题(dll生成失败|dll版本不对) C.源文件损坏 2、dll生成路径不对 3、对dll的引用丢失 阅读全文

posted @ 2017-12-11 17:13 菜鸟客栈 阅读(316) 评论(0) 推荐(0) 编辑

代码优化

摘要: 1.逆向思维:当你正向思维时,代码逻辑有可能较复杂,逆向思维有可能会简化逻辑 2.当代码操作较多时,可以将代码进行封装,实现代码的重用性,这样不会显得累赘 3.学会使用resharper的代码重构工具,优化代码 阅读全文

posted @ 2017-12-11 17:12 菜鸟客栈 阅读(105) 评论(0) 推荐(0) 编辑

导航

< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8
点击右上角即可分享
微信分享提示