0
点赞
收藏
分享

微信扫一扫

前端已死还是“娱乐至死”?做个清醒的前端

幸甚至哉歌以咏志 2023-04-28 阅读 68

一.项目需求:

1.调用外部接口链接,需要使用JWT获取token。
(本次案例使用JWT10.0,底层调用了Newtonsoft.Json13.0的方法)

二.项目难点:

1.金蝶云星空自带的Newtonsoft.Json 4.0版本过低,不能支持JWT所需的Newtonsoft.Json 13.0方法。

三.解决方案:

解释:替换金蝶自带的Newtonsoft.Json是不可能的,金蝶云星空底层的框架是调用了Newtonsoft.Json的方法的,直接替换会导致整个系统无法运行

1.思路:
a.反编译JWT 10.0,Newtonsoft.Json 13.0。
b. 在低版本Newtonsoft.Json的基础上,重写高版本Newtonsoft.Json的方法。
(本次案例是在Newtonsoft.Json4.0的基础上,实现Newtonsoft.Json13.0的部分方法,从而实现JWT获取token)
c.步骤就是visual studio哪里报错,在反编译工具中找到报错的属性或方法,添加到自定义类中

2.使用工具:Visual Studio(开发工具),ILSpy(反编译工具)

3.操作步骤:
a.新增自定义类JsonNetSerializer
b.新增自定义静态类ExpandMethod,里面写支持JsonNetSerializer的属性,方法
c.在Visual Studio 中报错的方法或者属性,在ILSpy工具中找到并粘贴到自定义方法中
d.调试运行,方案通过

4.代码如下:

在Newtonsoft.Json 13.0的条件下,调用JWT获取token。
代码块1:

//返货Token信息
    public static string JWTEncode(string ucode)
    {

        var secretKey = AppSettingService.SecretKey;//获取jwt密钥,示例是存放到配置文件

        if (!String.IsNullOrEmpty(secretKey))
        {
            var dic = new Dictionary<string, object>();
            dic["systemName"] = ucode;//增加用户名到字典
            var expiredTimeSpan = 1;
            if (!String.IsNullOrEmpty(AppSettingService.ExpiredTimeSpan))
            {
                var timeSpan = AppSettingService.ExpiredTimeSpan;
                if (System.Text.RegularExpressions.Regex.IsMatch(timeSpan, "^[1-9]\\d*$"))
                {
                    expiredTimeSpan = Convert.ToInt32(timeSpan);
                }
            }
            var jwtcreatedOver =
Math.Round((DateTime.UtcNow.AddMinutes(expiredTimeSpan) - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds + 5);
            dic["exp"] = jwtcreatedOver;// 指定token的生命周期。unix时间戳格式

            IJwtAlgorithm algorithm = new HMACSHA512Algorithm();
            IJsonSerializer serializer = new JsonNetSerializer();	//在Newtonsoft.Json 4.0的条件下,这个方法报错
            IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
            IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
            return encoder.Encode(dic, secretKey);//返回生成的token
        }
        else
            return "";
    }

在Newtonsoft.Json 4.0的条件下,重写上面案例的JsonNetSerializer方法,调用JWT获取token。
代码块2:
1.自定义静态JsonNetSerializer类:(直接从ILSpy反编译工具中整段复制出来)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace ZJYceshi
{
	//继承JWT.IJsonSerializer,后面才能进行类型转换
	public class JsonNetSerializer:JWT.IJsonSerializer
    {
		private readonly JsonSerializer _serializer;

		//ExpandMethod.CreateDefault()为自定义方法,原方法为JsonSerializer.CreateDefault(),属于Newtonsoft.Json 13.0的方法
		public JsonNetSerializer() : this(ExpandMethod.CreateDefault())
		{
		}

		public JsonNetSerializer(JsonSerializer serializer)
		{
			if (serializer == null)
			{
				throw new ArgumentNullException("serializer");
			}
			this._serializer = serializer;
		}

		public string Serialize(object obj)
		{
			if (obj == null)
			{
				throw new ArgumentNullException("obj");
			}
			StringBuilder stringBuilder = new StringBuilder();
			string result;
			using (StringWriter stringWriter = new StringWriter(stringBuilder))
			{
				using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter))
				{
					this._serializer.Serialize(jsonTextWriter, obj);
					result = stringBuilder.ToString();
				}
			}
			return result;
		}

		public object Deserialize(Type type, string json)
		{
			if (type == null)
			{
				throw new ArgumentNullException("type");
			}
			if (string.IsNullOrEmpty(json))
			{
				throw new ArgumentException("json");
			}
			object result;
			using (StringReader stringReader = new StringReader(json))
			{
				using (JsonTextReader jsonTextReader = new JsonTextReader(stringReader))
				{
					result = this._serializer.Deserialize(jsonTextReader, type);
				}
			}
			return result;
		}
	}
}

2.自定义静态ExpandMethod,将程序所需的Newtonsoft.Json 13.0的方法添加到此类中:

	using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Runtime.CompilerServices;
	using System.Text;
	using System.Threading.Tasks;
	using Newtonsoft.Json;
	
	namespace ZJYceshi
	{
	    public static class ExpandMethod
	    {

	        public static JsonSerializer CreateDefault()
	        {
	            Func<JsonSerializerSettings> expr_05 = ExpandMethod.DefaultSettings;
	            return JsonSerializer.Create((expr_05 != null) ? expr_05() : null);
	        }
	
	        [Nullable(new byte[]
	        {
	            2,
	            1
	        })]
	        public static Func<JsonSerializerSettings> DefaultSettings
	        {
	            [return: Nullable(new byte[]
	            {
	                2,
	                1
	            })]
	            get;
	            [param: Nullable(new byte[]
	            {
	                2,
	                1
	            })]
	            set;
	        }
	
	
	        [Embedded, AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false), CompilerGenerated]
	        internal sealed class NullableAttribute : Attribute
	        {
	            public readonly byte[] NullableFlags;
	
	            public NullableAttribute(byte b)
	            {
	                this.NullableFlags = new byte[]
	                {
	                b
	                };
	            }
	
	            public NullableAttribute(byte[] nullableFlags)
	            {
	                this.NullableFlags = nullableFlags;
	            }
	        }
	
	        [Embedded, CompilerGenerated]
	        internal sealed class EmbeddedAttribute : Attribute
	        {
	        }

    }
}

3.微调JWT获取Token方法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using Newtonsoft.Json;

namespace ZJYceshi
{
    public class ResultToken
    {

        public static string JWTEncode(string ucode)
        {

            var secretKey = AppSettingService.SecretKey;//获取jwt密钥,示例是存放到配置文件

            if (!String.IsNullOrEmpty(secretKey))
            {
                var dic = new Dictionary<string, object>();
                dic["systemName"] = ucode;//增加用户名到字典
                var expiredTimeSpan = 1;
                if (!String.IsNullOrEmpty(AppSettingService.ExpiredTimeSpan))
                {
                    var timeSpan = AppSettingService.ExpiredTimeSpan;
                    if (System.Text.RegularExpressions.Regex.IsMatch(timeSpan, "^[1-9]\\d*$"))
                    {
                        expiredTimeSpan = Convert.ToInt32(timeSpan);
                    }
                }
                var jwtcreatedOver =
    Math.Round((DateTime.UtcNow.AddMinutes(expiredTimeSpan) - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds + 5);
                dic["exp"] = jwtcreatedOver;// 指定token的生命周期。unix时间戳格式

                IJwtAlgorithm algorithm = new HMACSHA512Algorithm();
                //JsonSerializer serializer = new JsonNetSerializer();
                //调整语句,将紫定义JsonNetSerializer类,强制转换为JWT10.0的类
                IJsonSerializer serializer = (IJsonSerializer)(new JsonNetSerializer());
                IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
                return encoder.Encode(dic, secretKey);//返回生成的token
            }
            else
                return "";

        }

    }
}

5.方案结果:

1.Newtonsoft.Json 13.0 和 Newtonsoft.Json 4.0 环境下,JWT获取tokn均成功!

举报

相关推荐

0 条评论