文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C# 怎么实现Token的方法

2023-06-14 05:03

关注

本篇内容介绍了“C# 怎么实现Token的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

什么是JWT

JWT:Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

传统的session认证

我们知道,http协议本身是一种无状态的协议,而这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证,那么下一次请求时,用户还要再一次进行用户认证才行,因为根据http协议,我们并不能知道是哪个用户发出的请求,所以为了让我们的应用能识别是哪个用户发出的请求,我们只能在服务器存储一份用户登录的信息,这份登录信息会在响应时传递给浏览器,告诉其保存为cookie,以便下次请求时发送给我们的应用,这样我们的应用就能识别请求来自哪个用户了,这就是传统的基于session认证。

但是这种基于session的认证使应用本身很难得到扩展,随着不同客户端用户的增加,独立的服务器已无法承载更多的用户,而这时候基于session认证应用的问题就会暴露出来.

基于session认证所显露的问题

Session: 每个用户经过我们的应用认证之后,我们的应用都要在服务端做一次记录,以方便用户下次请求的鉴别,通常而言session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大。

扩展性: 用户认证之后,服务端做认证记录,如果认证的记录被保存在内存中的话,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权的资源,这样在分布式的应用上,相应的限制了负载均衡器的能力。这也意味着限制了应用的扩展能力。

CSRF: 因为是基于cookie来进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。

基于token的鉴权机制

基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利。

流程上是这样的:

这个token必须要在每次请求时传递给服务端,它应该保存在请求头里, 另外,服务端要支持CORS(跨来源资源共享)策略,一般我们在服务端这么做就可以了Access-Control-Allow-Origin: *。

那么我们现在回到JWT的主题上。

JWT的构成

第一部分我们称它为头部(header),第二部分我们称其为载荷(payload, 类似于飞机上承载的物品),第三部分是签证(signature).

C# MVC实现token

在NuGet中引用JWT

C# 怎么实现Token的方法

创建一个实体 UserInfo类

using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace WebApplication1.model{ public class UserInfo {  public string UserName { get; set; }  public string Pwd { get; set; } }}

创建JWT帮助类

using JWT;using JWT.Algorithms;using JWT.Serializers;using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace WebApplication1.model{ public class JwtHelp {  //私钥 web.config中配置  //"GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk";  private static string secret = "GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk";  //ConfigurationManager.AppSettings["Secret"].ToString();  /// <summary>  /// 生成JwtToken  /// </summary>  /// <param name="payload">不敏感的用户数据</param>  /// <returns></returns>  public static string SetJwtEncode(Dictionary<string, object> payload)  {   //格式如下   //var payload = new Dictionary<string, object>   //{   // { "username","admin" },   // { "pwd", "claim2-value" }   //};   IJwtAlgorithm algorithm = new HMACSHA256Algorithm();   IJsonSerializer serializer = new JsonNetSerializer();   IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();   IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);   var token = encoder.Encode(payload, secret);   return token;  }  /// <summary>  /// 根据jwtToken 获取实体  /// </summary>  /// <param name="token">jwtToken</param>  /// <returns></returns>  public static UserInfo GetJwtDecode(string token)  {   IJsonSerializer serializer = new JsonNetSerializer();   IDateTimeProvider provider = new UtcDateTimeProvider();   IJwtValidator validator = new JwtValidator(serializer, provider);   IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();   var algorithm = new HMACSHA256Algorithm();   IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm);   var userInfo = decoder.DecodeToObject<UserInfo>(token, secret, verify: true);//token为之前生成的字符串   return userInfo;  } }}

创建一个编码类DESCryption

using System;using System.Text;using System.Security.Cryptography;using System.IO;using System.Configuration;namespace JWT.MvcDemo.Help{ public class DESCryption {  /// <summary>  /// //注意了,是8个字符,64位  /// </summary>  private static string PrivateRsa = ConfigurationManager.AppSettings["PrivateRsa"];  /// <summary>  /// //注意了,是8个字符,64位  /// </summary>  private static string PublicRsa = ConfigurationManager.AppSettings["PublicRsa"];  /// <summary>  /// 加密  /// </summary>  /// <param name="data"></param>  /// <returns></returns>  public static string Encode(string data)  {   byte[] byKey = Encoding.ASCII.GetBytes(PrivateRsa);   byte[] byIV = Encoding.ASCII.GetBytes(PublicRsa);   DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();   int i = cryptoProvider.KeySize;   MemoryStream ms = new MemoryStream();   CryptoStream cst = new CryptoStream(ms, cryptoProvider.CreateEncryptor(byKey, byIV), CryptoStreamMode.Write);   StreamWriter sw = new StreamWriter(cst);   sw.Write(data);   sw.Flush();   cst.FlushFinalBlock();   sw.Flush();   return Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length);  }  /// <summary>  /// 解密  /// </summary>  /// <param name="data"></param>  /// <returns></returns>  public static string Decode(string data)  {   byte[] byKey = Encoding.ASCII.GetBytes(PrivateRsa);   byte[] byIV = Encoding.ASCII.GetBytes(PublicRsa);   byte[] byEnc;   try   {    byEnc = Convert.FromBase64String(data);   }   catch   {    return null;   }   DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();   MemoryStream ms = new MemoryStream(byEnc);   CryptoStream cst = new CryptoStream(ms, cryptoProvider.CreateDecryptor(byKey, byIV), CryptoStreamMode.Read);   StreamReader sr = new StreamReader(cst);   return sr.ReadToEnd();  } }}

创建一个返回消息类

using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace JWT.MvcDemo.Models{ public class DataResult {  /// <summary>  ///   /// </summary>  public string Token { get; set; }  public bool Success { get; set; }  public string Message { get; set; } }}

创建一个控制器用于生产token

using JWT.MvcDemo.Models;using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using WebApplication1.model;namespace WebApplication1.Controllers{ public class JwtController : Controller {  // GET: Jwt  public ActionResult Index()  {   return View();  }  /// <summary>  /// 创建jwtToken  /// </summary>  /// <param name="username"></param>  /// <param name="pwd"></param>  /// <returns></returns>  public ActionResult CreateToken(string username, string pwd)  {   DataResult result = new DataResult();   //假设用户名为"admin",密码为"123"    if (username == "admin" && pwd == "123")   {    var payload = new Dictionary<string, object>    {     { "username",username },     { "pwd", pwd }    };    result.Token = JwtHelp.SetJwtEncode(payload);    result.Success = true;    result.Message = "成功";   }   else   {    result.Token = "";    result.Success = false;    result.Message = "生成token失败";   }   //return Json(result);   //get请求需要修改成这样   return Json(result,JsonRequestBehavior.AllowGet);  } }}

创建一个自定义过滤器

using JWT.MvcDemo.Help;using System;using System.Collections.Generic;using System.Configuration;using System.Linq;using System.Web;using System.Web.Mvc;using System.Web.Security;using WebApplication1.model;namespace JWT.MvcDemo.App_Start{ public class MyAuthorizeAttribute : AuthorizeAttribute {  private readonly string TimeStamp = ConfigurationManager.AppSettings["TimeStamp"];  /// <summary>  /// 验证入口  /// </summary>  /// <param name="filterContext"></param>  public override void OnAuthorization(AuthorizationContext filterContext)  {   base.OnAuthorization(filterContext);  }  /// <summary>  /// 验证核心代码  /// </summary>  /// <param name="httpContext">fbc8ZBLd5ZbtCogcY9NUVV4HZbPln1lb</param>  /// <returns></returns>  protected override bool AuthorizeCore(HttpContextBase httpContext)  {   //前端请求api时会将token存放在名为"auth"的请求头中   var authHeader = httpContext.Request.Headers["auth"];   if (authHeader == null)    return false;   //请求参数   string requestTime = httpContext.Request["rtime"]; //请求时间经过DESC签名   if (string.IsNullOrEmpty(requestTime))    return false;   //模拟生成rtime 时间戳,即登录的时间,加密.       //实际生产中这段代码应该在请求段。此处只为了程序验证通过   string r= DESCryption.Encode(DateTime.Now.ToString());   requestTime = r;    //请求时间RSA解密后加上时间戳的时间即该请求的有效时间    DateTime Requestdt = DateTime.Parse(DESCryption.Decode(requestTime)).AddMinutes(int.Parse(TimeStamp));    DateTime Newdt = DateTime.Now; //服务器接收请求的当前时间   if (Requestdt < Newdt)   {    return false;   }   else   {    if (authHeader != null)    {     //进行其他操作     var userinfo = JwtHelp.GetJwtDecode(authHeader);     //举个例子 生成jwtToken 存入redis中      //这个地方用jwtToken当作key 获取实体val 然后看看jwtToken根据redis是否一样     if (userinfo.UserName == "admin" && userinfo.Pwd == "123")      return true;    }   }   return false;  }  /// <summary>  /// 验证失败处理  /// </summary>  /// <param name="filterContext"></param>  protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)  {   base.HandleUnauthorizedRequest(filterContext);   filterContext.Result = new RedirectResult("/Error");   filterContext.HttpContext.Response.Redirect("/Home/Error");  } }}

在要需要过滤的控制器方法上添加标签,标签就是自定义过滤器名称。

using JWT.MvcDemo.App_Start;using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;namespace WebApplication1.Controllers{ public class HomeController : Controller {  public ActionResult Index()  {   return View();  }  [HttpPost]  [MyAuthorize]  public string About()  {   string rtJson = "{\"code\": 0}";   try   {    rtJson = "{\"code\":0,\"data\":[],\"msg\":\"Your application description page.\",\"count\":1}";   }   catch   {    rtJson = "{\"code\": 0}";   }   return rtJson;  }  public ActionResult Contact()  {   ViewBag.Message = "Your contact page.";   return View();  } }}

测试获取token

C# 怎么实现Token的方法

客户端将token放入header中达到携带token目的。

C# 怎么实现Token的方法

需要在web.config 中添加设置值

 <add key="Secret" value="GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk"/>  <add key="PrivateRsa" value="GQDstcKs"/>  <add key="PublicRsa" value="DVvVBrkx0"/>  <add key="TimeStamp" value="2"/>

C# 怎么实现Token的方法

“C# 怎么实现Token的方法”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯