服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C# 如何实现Token

C# 如何实现Token

2022-11-08 12:00创客未来 C#

这篇文章主要介绍了C# 如何实现Token,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下

什么是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
  • 客户端存储token,并在每次请求时附送上这个token值
  • 服务端验证token值,并返回数据

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

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

 

JWT的构成

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

 

C# MVC实现token

1.在NuGet中引用JWT

C# 如何实现Token

2.创建一个实体 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; }
}
}

3.创建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;
}
}
}

4.创建一个编码类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();
}

}
}

5.创建一个返回消息类

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; }

}
}

6.创建一个控制器用于生产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);
}
}
}

7.创建一个自定义过滤器

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");
}


}
}

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

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();
}
}
}

9.测试获取token

C# 如何实现Token

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

C# 如何实现Token

11.需要在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的详细内容,更多关于C# 实现Token的资料请关注服务器之家其它相关文章!

原文链接:https://www.cnblogs.com/ckfuture/p/14516741.html

延伸 · 阅读

精彩推荐
  • C#C# listview 点击列头排序的实例

    C# listview 点击列头排序的实例

    下面小编就为大家带来一篇C# listview 点击列头排序的实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    C#教程网5552021-12-22
  • C#C#中List和SortedList的简介

    C#中List和SortedList的简介

    今天小编就为大家分享一篇关于C#中List和SortedList的简介,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看...

    Czhenya6962022-03-03
  • C#微信开发--企业转账到用户

    微信开发--企业转账到用户

    本文主要介绍了微信开发--企业转账到用户的实现方法与步骤。具有很好的参考价值,下面跟着小编一起来看下吧...

    stoneniqiu9352021-12-20
  • C#C# 利用AForge实现摄像头信息采集

    C# 利用AForge实现摄像头信息采集

    这篇文章主要介绍了C# 如何利用AForge实现摄像头信息采集,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...

    Alan.hsiang7032022-09-26
  • C#如何最大限度地降低多线程C#代码的复杂性

    如何最大限度地降低多线程C#代码的复杂性

    这篇文章主要介绍了如何最大限度地降低多线程C#代码的复杂性,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    楚人Leo10062022-07-14
  • C#C#给PDF文件添加水印

    C#给PDF文件添加水印

    这篇文章主要为大家详细介绍了C#给PDF文件添加水印的相关代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    DODONG5672021-12-30
  • C#C# winform点击生成二维码实例代码

    C# winform点击生成二维码实例代码

    这篇文章主要介绍了 C# winform点击生成二维码实例代码,需要的朋友可以参考下...

    zhaoyu_m698272022-01-04
  • C#C#版Windows服务安装卸载小工具

    C#版Windows服务安装卸载小工具

    这篇文章主要为大家推荐了一款C#版Windows服务安装卸载小工具,小巧灵活的控制台程序,希望大家喜欢,感兴趣的小伙伴们可以参考一下...

    韩天伟7592021-12-01