添加项目
This commit is contained in:
12
WPFUI.Test/Web/AuthOperation.cs
Normal file
12
WPFUI.Test/Web/AuthOperation.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace WPFUI.Test
|
||||
{
|
||||
[Serializable]
|
||||
public class AuthOperation
|
||||
{
|
||||
public string FolderCode { get; set; }
|
||||
|
||||
public List<string> SelectedOperationList { get; set; }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
114
WPFUI.Test/Web/AuthenticationService.cs
Normal file
114
WPFUI.Test/Web/AuthenticationService.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
|
||||
using Flurl.Http;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Encodings;
|
||||
using Org.BouncyCastle.Crypto.Engines;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.OpenSsl;
|
||||
using Org.BouncyCastle.Security;
|
||||
|
||||
namespace WPFUI.Test.Web
|
||||
{
|
||||
public class AuthenticationService
|
||||
{
|
||||
private readonly DispatcherTimer _sessionTimer;
|
||||
private readonly TimeSpan _sessionTimeout = TimeSpan.FromMinutes(30); // 单次 Session 时长
|
||||
|
||||
public bool IsAuthenticated { get; private set; }
|
||||
public event Action SessionExpired;
|
||||
public event Action LoggedOut;
|
||||
|
||||
public AuthenticationService()
|
||||
{
|
||||
_sessionTimer = new DispatcherTimer { Interval = _sessionTimeout };
|
||||
_sessionTimer.Tick += (s, e) =>
|
||||
{
|
||||
Logout();
|
||||
SessionExpired?.Invoke();
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<ResponseVO> LoginAsync(string username, string password)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 1. 取公钥
|
||||
var keyJson = await Settings.Default.PublicKeyUrl.GetStringAsync();
|
||||
var pubKeyVO = JsonConvert.DeserializeObject<PublicKeyVO>(keyJson);
|
||||
if (pubKeyVO.Successful)
|
||||
{
|
||||
// 2. 用 BouncyCastle 加密
|
||||
var encrypted = RSAHelper.EncryptByJavaKey(pubKeyVO.Data.PublicKey, $"{password}");
|
||||
|
||||
var jsonData = $"{{\"accountName\":\"{username}\",\"password\":\"{encrypted}\",\"uuid\":\"{pubKeyVO.Data.UUID}\",\"appVersion\":\"newversion\"}}";
|
||||
// 3. 发送登录请求
|
||||
var respones = GetStreamReader(Settings.Default.LoginUrl, jsonData);
|
||||
var settings = new JsonSerializerSettings
|
||||
{
|
||||
MissingMemberHandling = MissingMemberHandling.Ignore
|
||||
};
|
||||
|
||||
return JsonConvert.DeserializeObject<ResponseVO>(respones, settings);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("获取不到用户公钥信息,请联系管理员");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private string GetStreamReader(string url, string postData, string auth = "", int timeout = 60000, string encode = "utf-8", string contentType = "application/json", string method = "POST")
|
||||
{
|
||||
var data = Encoding.GetEncoding(encode).GetBytes(postData);
|
||||
var webRequest = (HttpWebRequest)WebRequest.Create(url);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(auth))
|
||||
{
|
||||
var athu = "Authorization:" + auth;
|
||||
var whc = new WebHeaderCollection();
|
||||
whc.Add(athu);
|
||||
webRequest.Headers.Add(whc);
|
||||
}
|
||||
webRequest.Method = method;
|
||||
webRequest.ContentType = contentType + ";" + encode;
|
||||
webRequest.ContentLength = data.Length;
|
||||
webRequest.Timeout = timeout;
|
||||
var requestStream = webRequest.GetRequestStream();
|
||||
requestStream.Write(data, 0, data.Length);
|
||||
var webResponse = (HttpWebResponse)webRequest.GetResponse();
|
||||
var responseStream = webResponse.GetResponseStream();
|
||||
if (responseStream == null) { return ""; }
|
||||
var streamReader = new StreamReader(responseStream, Encoding.GetEncoding(encode));
|
||||
return streamReader.ReadToEnd();
|
||||
}
|
||||
|
||||
public void Logout()
|
||||
{
|
||||
if (IsAuthenticated)
|
||||
{
|
||||
IsAuthenticated = false;
|
||||
_sessionTimer.Stop();
|
||||
LoggedOut?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
16
WPFUI.Test/Web/DataVO.cs
Normal file
16
WPFUI.Test/Web/DataVO.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace WPFUI.Test
|
||||
{
|
||||
[Serializable]
|
||||
public class DataVO
|
||||
{
|
||||
[JsonProperty("publicKey")]
|
||||
public string PublicKey { get; set; } = string.Empty;
|
||||
[JsonProperty("uuid")]
|
||||
public string UUID { get; set; } = string.Empty;
|
||||
public string Token { get; set; }
|
||||
public UserInfoVO UserInfoVO { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
234
WPFUI.Test/Web/LLMClient.cs
Normal file
234
WPFUI.Test/Web/LLMClient.cs
Normal file
@@ -0,0 +1,234 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace WPFUI.Test.Web
|
||||
{
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
internal class LLMClient
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly List<ChatMessage> _conversationHistory;
|
||||
private bool _disposed;
|
||||
|
||||
/// <summary>
|
||||
/// 创建LLM客户端实例
|
||||
/// </summary>
|
||||
/// <param name="apiKey">API密钥</param>
|
||||
/// <param name="endpoint">API端点地址</param>
|
||||
/// <param name="systemPrompt">可选的系统提示词</param>
|
||||
public LLMClient(string apiKey, string endpoint, string systemPrompt = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(apiKey))
|
||||
throw new ArgumentNullException(nameof(apiKey));
|
||||
|
||||
if (string.IsNullOrEmpty(endpoint))
|
||||
throw new ArgumentNullException(nameof(endpoint));
|
||||
|
||||
_httpClient = new HttpClient
|
||||
{
|
||||
BaseAddress = new Uri(endpoint)
|
||||
};
|
||||
|
||||
_httpClient.DefaultRequestHeaders.Authorization =
|
||||
new AuthenticationHeaderValue("Bearer", apiKey);
|
||||
_httpClient.DefaultRequestHeaders.Accept.Add(
|
||||
new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
|
||||
// 初始化对话历史,可选添加系统提示
|
||||
_conversationHistory = new List<ChatMessage>();
|
||||
if (!string.IsNullOrEmpty(systemPrompt))
|
||||
{
|
||||
_conversationHistory.Add(new ChatMessage("system", systemPrompt));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前对话历史
|
||||
/// </summary>
|
||||
public IReadOnlyList<ChatMessage> ConversationHistory => _conversationHistory.AsReadOnly();
|
||||
|
||||
/// <summary>
|
||||
/// 清除对话历史(保留系统提示)
|
||||
/// </summary>
|
||||
public void ClearHistory()
|
||||
{
|
||||
if (_conversationHistory.Count > 0 && _conversationHistory[0].Role == "system")
|
||||
{
|
||||
var systemMessage = _conversationHistory[0];
|
||||
_conversationHistory.Clear();
|
||||
_conversationHistory.Add(systemMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
_conversationHistory.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送非流式请求获取完整响应
|
||||
/// </summary>
|
||||
public async Task<string> SendMessageAsync(string userMessage, string model = "qwen-max")
|
||||
{
|
||||
// 添加用户消息到历史
|
||||
_conversationHistory.Add(new ChatMessage("user", userMessage));
|
||||
|
||||
// 创建请求内容(包含完整对话历史)
|
||||
var request = CreateRequestContent(_conversationHistory, model);
|
||||
|
||||
HttpResponseMessage response = await _httpClient.PostAsync("", request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
string jsonResponse = await response.Content.ReadAsStringAsync();
|
||||
|
||||
// 解析响应并添加到对话历史
|
||||
var responseObj = JsonConvert.DeserializeObject<dynamic>(jsonResponse);
|
||||
string assistantReply = responseObj?.output?.choices?[0]?.message?.content;
|
||||
|
||||
if (!string.IsNullOrEmpty(assistantReply))
|
||||
{
|
||||
_conversationHistory.Add(new ChatMessage("assistant", assistantReply));
|
||||
}
|
||||
|
||||
return assistantReply;
|
||||
}
|
||||
|
||||
// 修正关键:使用SendAsync替代PostAsync解决.NET Framework参数问题
|
||||
public async Task SendMessageStreamAsync(string userMessage,
|
||||
Action<string> onChunkReceived,
|
||||
string model = "qwen-max",
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
_conversationHistory.Add(new ChatMessage("user", userMessage));
|
||||
_conversationHistory.Add(new ChatMessage("assistant", "")); // 占位符
|
||||
|
||||
var request = CreateRequestContent(_conversationHistory, model, true);
|
||||
|
||||
// 创建HttpRequestMessage对象(.NET Framework兼容方式)
|
||||
var httpRequest = new HttpRequestMessage(HttpMethod.Post, _httpClient.BaseAddress)
|
||||
{
|
||||
Content = request
|
||||
};
|
||||
|
||||
// 使用SendAsync并指定HttpCompletionOption(.NET Framework兼容)
|
||||
using (var response = await _httpClient.SendAsync(
|
||||
httpRequest,
|
||||
HttpCompletionOption.ResponseHeadersRead,
|
||||
cancellationToken))
|
||||
{
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
using (var stream = await response.Content.ReadAsStreamAsync())
|
||||
using (var reader = new StreamReader(stream, Encoding.UTF8))
|
||||
{
|
||||
string fullResponse = "";
|
||||
while (!reader.EndOfStream)
|
||||
{
|
||||
string line = await reader.ReadLineAsync();
|
||||
if (string.IsNullOrWhiteSpace(line)) continue;
|
||||
|
||||
// 修正:正确处理阿里云SSE格式(data: {...})
|
||||
if (line.StartsWith("data: "))
|
||||
{
|
||||
string jsonData = line.Substring(6);
|
||||
try
|
||||
{
|
||||
if (jsonData.Trim() == "[DONE]")
|
||||
continue;
|
||||
|
||||
var json = JsonConvert.DeserializeObject<dynamic>(jsonData);
|
||||
string content = json?.output?.choices?[0]?.delta?.content;
|
||||
|
||||
if (!string.IsNullOrEmpty(content))
|
||||
{
|
||||
fullResponse += content;
|
||||
onChunkReceived?.Invoke(content);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 忽略无法解析的数据
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新助手消息的实际内容
|
||||
if (_conversationHistory.Count > 0)
|
||||
{
|
||||
_conversationHistory[_conversationHistory.Count - 1] =
|
||||
new ChatMessage("assistant", fullResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private StringContent CreateRequestContent(List<ChatMessage> messages, string model, bool stream = false)
|
||||
{
|
||||
// 构建符合通义千问API的消息结构
|
||||
var requestBody = new
|
||||
{
|
||||
model,
|
||||
input = new
|
||||
{
|
||||
messages = messages.ConvertAll(m => new { role = m.Role, content = m.Content })
|
||||
},
|
||||
parameters = new
|
||||
{
|
||||
result_format = "message"
|
||||
},
|
||||
stream
|
||||
};
|
||||
|
||||
string json = JsonConvert.SerializeObject(requestBody);
|
||||
return new StringContent(json, Encoding.UTF8, "application/json");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_httpClient?.Dispose();
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 表示对话中的单条消息
|
||||
/// </summary>
|
||||
public class ChatMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// 消息角色: user, assistant, system
|
||||
/// </summary>
|
||||
public string Role { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 消息内容
|
||||
/// </summary>
|
||||
public string Content { get; set; }
|
||||
|
||||
public ChatMessage(string role, string content)
|
||||
{
|
||||
Role = role;
|
||||
Content = content;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
WPFUI.Test/Web/Permission.cs
Normal file
12
WPFUI.Test/Web/Permission.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace WPFUI.Test
|
||||
{
|
||||
[Serializable]
|
||||
public class Permission
|
||||
{
|
||||
public List<AuthOperation> AuthOperationVO { get; set; }
|
||||
public bool IsAdmin { get; set; }
|
||||
|
||||
public Dictionary<string, string> Role { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
22
WPFUI.Test/Web/PublicKeyVO.cs
Normal file
22
WPFUI.Test/Web/PublicKeyVO.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace WPFUI.Test
|
||||
{
|
||||
[Serializable]
|
||||
internal class PublicKeyVO
|
||||
{
|
||||
[JsonProperty("message")]
|
||||
public string Message { get; set; } = string.Empty;
|
||||
[JsonProperty("code")]
|
||||
public string Code { get; set; } = string.Empty;
|
||||
[JsonProperty("data")]
|
||||
public DataVO Data { get; set; }
|
||||
[JsonProperty("exception")]
|
||||
public string Exception { get; set; }
|
||||
[JsonProperty("failed")]
|
||||
public bool Failed { get; set; }
|
||||
[JsonProperty("successful")]
|
||||
public bool Successful { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
382
WPFUI.Test/Web/RSAHelper.cs
Normal file
382
WPFUI.Test/Web/RSAHelper.cs
Normal file
@@ -0,0 +1,382 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WPFUI.Test.Web
|
||||
{
|
||||
public class RSAHelper
|
||||
{
|
||||
//private static String pubJavaKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCHoDne3LBben7VT0dvBmmpbO2iNet/PBkTvkWE" +
|
||||
// "/WfYO8Yx+oNcLXBkyxLBlV+HRAjOG1LNmzhpHQySLNc+KK/iXaAPyHSZAEGsA/eh731FCKLcSlEA" +
|
||||
// "M0rXS2HpeJFvLEfj5q9Yabzp/TkQBUt3epxZ/0BIXFCxa8Grr0w6oBs0NwIDAQAB";
|
||||
|
||||
//private static string PublicKey =
|
||||
|
||||
//"<RSAKeyValue><Modulus>6CdsXgYOyya/yQH" +
|
||||
//"TO96dB3gEurM2UQDDVGrZoe6RcAVTxAqDDf5L" +
|
||||
//"wPycZwtNOx3Cfy44/D5Mj86koPew5soFIz9sx" +
|
||||
//"PAHRF5hcqJoG+q+UfUYTHYCsMH2cnqGVtnQiE" +
|
||||
//"/PMRMmY0RwEfMIo+TDpq3QyO03MaEsDGf13sP" +
|
||||
//"w9YRXiac=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
|
||||
|
||||
private static string privateKey =
|
||||
"<RSAKeyValue><Modulus>6CdsXgYOyya/yQH" +
|
||||
"TO96dB3gEurM2UQDDVGrZoe6RcAVTxAqDDf5L" +
|
||||
"wPycZwtNOx3Cfy44/D5Mj86koPew5soFIz9sx" +
|
||||
"PAHRF5hcqJoG+q+UfUYTHYCsMH2cnqGVtnQiE" +
|
||||
"/PMRMmY0RwEfMIo+TDpq3QyO03MaEsDGf13sP" +
|
||||
"w9YRXiac=</Modulus><Exponent>AQAB</Exponent>" +
|
||||
"<P>/aoce2r6tonjzt1IQI6FM4ysR40j/gKvt4d" +
|
||||
|
||||
"L411pUop1Zg61KvCm990M4uN6K8R/DUvAQdrRd" +
|
||||
|
||||
"VgzvvAxXD7ESw==</P><Q>6kqclrEunX/fmOle" +
|
||||
|
||||
"VTxG4oEpXY4IJumXkLpylNR3vhlXf6ZF9obEpG" +
|
||||
|
||||
"lq0N7sX2HBxa7T2a0WznOAb0si8FuelQ==</Q>" +
|
||||
|
||||
"<DP>3XEvxB40GD5v/Rr4BENmzQW1MBFqpki6FU" +
|
||||
|
||||
"GrYiUd2My+iAW26nGDkUYMBdYHxUWYlIbYo6Te" +
|
||||
|
||||
"zc3d/oW40YqJ2Q==</DP><DQ>LK0XmQCmY/ArY" +
|
||||
|
||||
"gw2Kci5t51rluRrl4f5l+aFzO2K+9v3PGcndjA" +
|
||||
|
||||
"StUtIzBWGO1X3zktdKGgCLlIGDrLkMbM21Q==</DQ><InverseQ>" +
|
||||
|
||||
"GqC4Wwsk2fdvJ9dmgYlej8mTDBWg0Wm6aqb5kjn" +
|
||||
|
||||
"cWK6WUa6CfD+XxfewIIq26+4Etm2A8IAtRdwPl4" +
|
||||
|
||||
"aPjSfWdA==</InverseQ><D>a1qfsDMY8DSxB2D" +
|
||||
|
||||
"Cr7LX5rZHaZaqDXdO3GC01z8dHjI4dDVwOS5ZFZ" +
|
||||
|
||||
"s7MCN3yViPsoRLccnVWcLzOkSQF4lgKfTq3IH40" +
|
||||
|
||||
"H5N4gg41as9GbD0g9FC3n5IT4VlVxn9ZdW+WQry" +
|
||||
|
||||
"oHdbiIAiNpFKxL/DIEERur4sE1Jt9VdZsH24CJE=</D></RSAKeyValue>";
|
||||
|
||||
public static string Decrypt(string base64code)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
//Create a UnicodeEncoder to convert between byte array and string.
|
||||
UnicodeEncoding ByteConverter = new UnicodeEncoding();
|
||||
|
||||
//Create a new instance of RSACryptoServiceProvider to generate
|
||||
//public and private key data.
|
||||
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
|
||||
RSA.FromXmlString(privateKey);
|
||||
byte[] encryptedData;
|
||||
byte[] decryptedData;
|
||||
encryptedData = Convert.FromBase64String(base64code);
|
||||
|
||||
//Pass the data to DECRYPT, the private key information
|
||||
//(using RSACryptoServiceProvider.ExportParameters(true),
|
||||
//and a boolean flag specifying no OAEP padding.
|
||||
decryptedData = RSADecrypt(encryptedData, RSA.ExportParameters(true), false);
|
||||
//Display the decrypted plaintext to the console.
|
||||
return ByteConverter.GetString(decryptedData);
|
||||
|
||||
}
|
||||
|
||||
catch (Exception exc)
|
||||
{
|
||||
//Exceptions.LogException(exc);
|
||||
Console.WriteLine(exc.Message);
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加密
|
||||
/// </summary>
|
||||
/// <param name="toEncryptString"></param>
|
||||
/// <returns></returns>
|
||||
static public string Encrypt(string toEncryptString)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
//string key = "";
|
||||
|
||||
//Create a UnicodeEncoder to convert between byte array and string.
|
||||
UnicodeEncoding ByteConverter = new UnicodeEncoding();
|
||||
//Create byte arrays to hold original, encrypted, and decrypted data.
|
||||
|
||||
byte[] dataToEncrypt = ByteConverter.GetBytes(toEncryptString);
|
||||
byte[] encryptedData;
|
||||
//byte[] decryptedData;
|
||||
//Create a new instance of RSACryptoServiceProvider to generate
|
||||
//public and private key data.
|
||||
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
|
||||
RSA.FromXmlString(privateKey);
|
||||
|
||||
|
||||
|
||||
//Pass the data to ENCRYPT, the public key information
|
||||
//(using RSACryptoServiceProvider.ExportParameters(false),
|
||||
//and a boolean flag specifying no OAEP padding.
|
||||
encryptedData = RSAEncrypt(dataToEncrypt, RSA.ExportParameters(false), false);
|
||||
string base64code = Convert.ToBase64String(encryptedData);
|
||||
return base64code;
|
||||
}
|
||||
|
||||
catch (Exception exc)
|
||||
{
|
||||
|
||||
//Catch this exception in case the encryption did
|
||||
//not succeed.
|
||||
//Exceptions.LogException(exc);
|
||||
Console.WriteLine(exc.Message);
|
||||
return string.Empty;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解密
|
||||
/// </summary>
|
||||
/// <param name="DataToEncrypt"></param>
|
||||
/// <param name="RSAKeyInfo"></param>
|
||||
/// <param name="DoOAEPPadding"></param>
|
||||
/// <returns></returns>
|
||||
static private byte[] RSAEncrypt(byte[] DataToEncrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
//Create a new instance of RSACryptoServiceProvider.
|
||||
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
|
||||
|
||||
//Import the RSA Key information. This only needs
|
||||
//toinclude the public key information.
|
||||
RSA.ImportParameters(RSAKeyInfo);
|
||||
//Encrypt the passed byte array and specify OAEP padding.
|
||||
//OAEP padding is only available on Microsoft Windows XP or
|
||||
//later.
|
||||
return RSA.Encrypt(DataToEncrypt, DoOAEPPadding);
|
||||
}
|
||||
|
||||
//Catch and display a CryptographicException
|
||||
//to the console.
|
||||
catch (CryptographicException e)
|
||||
{
|
||||
//Exceptions.LogException(e);
|
||||
Console.WriteLine(e.Message);
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static private byte[] RSADecrypt(byte[] DataToDecrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
//Create a new instance of RSACryptoServiceProvider.
|
||||
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
|
||||
|
||||
//Import the RSA Key information. This needs
|
||||
//to include the private key information.
|
||||
RSA.ImportParameters(RSAKeyInfo);
|
||||
|
||||
//Decrypt the passed byte array and specify OAEP padding.
|
||||
//OAEP padding is only available on Microsoft Windows XP or
|
||||
//later.
|
||||
return RSA.Decrypt(DataToDecrypt, DoOAEPPadding);
|
||||
}
|
||||
|
||||
//Catch and display a CryptographicException
|
||||
//to the console.
|
||||
catch (CryptographicException e)
|
||||
{
|
||||
//Exceptions.LogException(e);
|
||||
Console.WriteLine(e.Message);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 加密
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public static string EncryptByJavaKey(string pubKey, string data)
|
||||
{
|
||||
//const int PROVIDER_RSA_FULL = 1;
|
||||
//const string CONTAINER_NAME = "Tracker";
|
||||
|
||||
//CspParameters cspParams;
|
||||
//cspParams = new CspParameters(PROVIDER_RSA_FULL);
|
||||
//cspParams.KeyContainerName = CONTAINER_NAME;
|
||||
//RSACryptoServiceProvider rsa1 = new RSACryptoServiceProvider(cspParams);
|
||||
//rsa1.FromXmlString("<RSAKeyValue><Modulus>2rRVVVFJRbH/wAPDtnwZwu+nxU+AZ6uXxh/sW+AMCBogg7vndZsnRiHoLttYYPqOyOhfgaBOQogrIfrKL4lipK4m52SBzw/FfcM9DsKs/rYR83tBLiIAfgdnVjF27tZID+HJMFTiI30mALjr7+tfp+2lIACXA1RIKTk7S9pDmX8=</Modulus><Exponent>AQAB</Exponent><P>92jJJyzFBSx6gL4Y1YpALmc5CNjoE/wETjqb3ci2v0+3rZWvJKmKy1ZEdlXpyuvXVksJ6cMdUpNAkMknUk9pTQ==</P><Q>4kxkABZOXyDLryYGCGY0b8N0FIdu5BTCFDYEdcatxl/f7ZGDS1NgHJpUWxkVXFfHy2Y/GuDOIbpcwlsO739H+w==</Q><DP>5bNFvrdUHF+VRN45VFjNCcgQLeSkY5mBrdfASoNFGA29LM5iE5nNIMfxPCS7sQiRnq6Af6YFHVtVgJchiMvtqQ==</DP><DQ>j+ng1qVY5epnXlWiFIla45C7K6sNfIMvAcdwgq39KWEjeWPGyYqWXtpOtzh2eylf6Bx4GVHKBW0NPJTIJMsfLQ==</DQ><InverseQ>8uu0dfPVDqB2qFM1Vdi8hl+2uZtN7gjT2co1cEWy29HVYBZD0k9KKCf2PbkeuSfpgFpE70wW5Hrp8V7l/SwSOw==</InverseQ><D>MM/c18zroJ2Iqi9s5/asvUBF3pjO3NSEbFjFpP/NT6WdKimvECWPz2xT6NlV0Vc6tQaAAmtn7Bt+HPhfVdrA4/ysYVe3/6TWkPjW+bvAhMWu/ZqISx11/jPYSGD9g3ZXgUiqcQM8UbOjlswoq4fpheEXTB0xdVutDLpO3qgHN6k=</D></RSAKeyValue>");
|
||||
byte[] bytes = Convert.FromBase64String(pubKey);
|
||||
RSACryptoServiceProvider rsa1 = DecodeX509PublicKey(bytes);
|
||||
|
||||
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
|
||||
byte[] textBytes = encoding.GetBytes(data);
|
||||
byte[] encryptedOutput = rsa1.Encrypt(textBytes, false);
|
||||
string outputB64 = Convert.ToBase64String(encryptedOutput);
|
||||
//Debug.WriteLine(outputB64);
|
||||
return outputB64;
|
||||
}
|
||||
|
||||
public static RSACryptoServiceProvider DecodeX509PublicKey(byte[] x509key)
|
||||
{
|
||||
byte[] SeqOID = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 };
|
||||
|
||||
MemoryStream ms = new MemoryStream(x509key);
|
||||
BinaryReader reader = new BinaryReader(ms);
|
||||
|
||||
if (reader.ReadByte() == 0x30)
|
||||
ReadASNLength(reader); //skip the size
|
||||
else
|
||||
return null;
|
||||
|
||||
int identifierSize = 0; //total length of Object Identifier section
|
||||
if (reader.ReadByte() == 0x30)
|
||||
identifierSize = ReadASNLength(reader);
|
||||
else
|
||||
return null;
|
||||
|
||||
if (reader.ReadByte() == 0x06) //is the next element an object identifier?
|
||||
{
|
||||
int oidLength = ReadASNLength(reader);
|
||||
byte[] oidBytes = new byte[oidLength];
|
||||
reader.Read(oidBytes, 0, oidBytes.Length);
|
||||
if (oidBytes.SequenceEqual(SeqOID) == false) //is the object identifier rsaEncryption PKCS#1?
|
||||
return null;
|
||||
|
||||
int remainingBytes = identifierSize - 2 - oidBytes.Length;
|
||||
reader.ReadBytes(remainingBytes);
|
||||
}
|
||||
|
||||
if (reader.ReadByte() == 0x03) //is the next element a bit string?
|
||||
{
|
||||
ReadASNLength(reader); //skip the size
|
||||
reader.ReadByte(); //skip unused bits indicator
|
||||
if (reader.ReadByte() == 0x30)
|
||||
{
|
||||
ReadASNLength(reader); //skip the size
|
||||
if (reader.ReadByte() == 0x02) //is it an integer?
|
||||
{
|
||||
int modulusSize = ReadASNLength(reader);
|
||||
byte[] modulus = new byte[modulusSize];
|
||||
reader.Read(modulus, 0, modulus.Length);
|
||||
if (modulus[0] == 0x00) //strip off the first byte if it's 0
|
||||
{
|
||||
byte[] tempModulus = new byte[modulus.Length - 1];
|
||||
Array.Copy(modulus, 1, tempModulus, 0, modulus.Length - 1);
|
||||
modulus = tempModulus;
|
||||
}
|
||||
|
||||
if (reader.ReadByte() == 0x02) //is it an integer?
|
||||
{
|
||||
int exponentSize = ReadASNLength(reader);
|
||||
byte[] exponent = new byte[exponentSize];
|
||||
reader.Read(exponent, 0, exponent.Length);
|
||||
|
||||
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
|
||||
RSAParameters RSAKeyInfo = new RSAParameters();
|
||||
RSAKeyInfo.Modulus = modulus;
|
||||
RSAKeyInfo.Exponent = exponent;
|
||||
RSA.ImportParameters(RSAKeyInfo);
|
||||
return RSA;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int ReadASNLength(BinaryReader reader)
|
||||
{
|
||||
//Note: this method only reads lengths up to 4 bytes long as
|
||||
//this is satisfactory for the majority of situations.
|
||||
int length = reader.ReadByte();
|
||||
if ((length & 0x00000080) == 0x00000080) //is the length greater than 1 byte
|
||||
{
|
||||
int count = length & 0x0000000f;
|
||||
byte[] lengthBytes = new byte[4];
|
||||
reader.Read(lengthBytes, 4 - count, count);
|
||||
Array.Reverse(lengthBytes); //
|
||||
length = BitConverter.ToInt32(lengthBytes, 0);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
public static string EncodeBase64(string code)
|
||||
{
|
||||
return EncodeBase64("utf-8", code);
|
||||
}
|
||||
|
||||
public static string DecodeBase64(string code)
|
||||
{
|
||||
return DecodeBase64("utf-8", code);
|
||||
}
|
||||
|
||||
public static string EncodeBase64(string code_type, string code)
|
||||
{
|
||||
string encode = string.Empty;
|
||||
byte[] bytes = Encoding.GetEncoding(code_type).GetBytes(code);
|
||||
try
|
||||
{
|
||||
encode = Convert.ToBase64String(bytes);
|
||||
}
|
||||
catch
|
||||
{
|
||||
encode = code;
|
||||
}
|
||||
return encode;
|
||||
}
|
||||
|
||||
public static string DecodeBase64(string code_type, string code)
|
||||
{
|
||||
string decode = string.Empty;
|
||||
try
|
||||
{
|
||||
byte[] bytes = Convert.FromBase64String(code);
|
||||
decode = Encoding.GetEncoding(code_type).GetString(bytes);
|
||||
}
|
||||
catch
|
||||
{
|
||||
decode = code;
|
||||
}
|
||||
return decode;
|
||||
}
|
||||
|
||||
////测试代码:
|
||||
|
||||
//static void Main(string[] args)
|
||||
//{
|
||||
// string encodeString = RSAHelper.Encrypt("1234567");
|
||||
// Console.WriteLine(encodeString);
|
||||
|
||||
|
||||
// string decode = RSAHelper.Decrypt(encodeString);
|
||||
// Console.WriteLine(decode);
|
||||
|
||||
// Console.ReadLine();
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
29
WPFUI.Test/Web/ResponseVO.cs
Normal file
29
WPFUI.Test/Web/ResponseVO.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using MaterialDesignThemes.Wpf.Converters;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace WPFUI.Test
|
||||
{
|
||||
[Serializable]
|
||||
public class ResponseVO
|
||||
{
|
||||
public string Message { get; set; }
|
||||
public int Code { get; set; }
|
||||
|
||||
public DataVO Data { get; set; }
|
||||
|
||||
public bool Successful { get; set; }
|
||||
public bool Failed { get; set; }
|
||||
//public string Exception { get; set; }
|
||||
public Dictionary<string, object> Exception { get; set; }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
72
WPFUI.Test/Web/UserInfoVO.cs
Normal file
72
WPFUI.Test/Web/UserInfoVO.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace WPFUI.Test
|
||||
{
|
||||
[Serializable]
|
||||
public partial class UserInfoVO : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
public string _accountName;
|
||||
[ObservableProperty]
|
||||
|
||||
public string _nameCn;
|
||||
[ObservableProperty]
|
||||
|
||||
public string _phone;
|
||||
|
||||
|
||||
[ObservableProperty]
|
||||
|
||||
public string _companyNameCn;
|
||||
|
||||
public string UserCode { get; set; }
|
||||
public string NameEn { get; set; }
|
||||
public string Nickname { get; set; }
|
||||
public string IsDimission { get; set; }
|
||||
public string Education { get; set; }
|
||||
public string Seniority { get; set; }
|
||||
public string Sex { get; set; }
|
||||
public string Age { get; set; }
|
||||
public string CountryCode { get; set; }
|
||||
public string ProvinceCode { get; set; }
|
||||
public string CityCode { get; set; }
|
||||
public string Email { get; set; }
|
||||
|
||||
public string Address { get; set; }
|
||||
public string EmployeeNum { get; set; }
|
||||
public string Position { get; set; }
|
||||
public string ProfessionalPost { get; set; }
|
||||
public string CompanyCode { get; set; }
|
||||
public string DepartmentCode { get; set; }
|
||||
public string Sources { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string TelPhone { get; set; }
|
||||
public string CompanyId { get; set; }
|
||||
public string FinishPercentage { get; set; }
|
||||
public string Identifier { get; set; }
|
||||
public string Id { get; set; }
|
||||
public string IsDeleted { get; set; }
|
||||
public string CreatedBy { get; set; }
|
||||
public string CreationTime { get; set; }
|
||||
public string UpdatedBy { get; set; }
|
||||
public string UpdateTime { get; set; }
|
||||
public string DeptParentCode { get; set; }
|
||||
public string DeptNameCn { get; set; }
|
||||
public int UnitType { get; set; }
|
||||
|
||||
public string DeptNameEn { get; set; }
|
||||
public string DeptPath { get; set; }
|
||||
public string DeptPathName { get; set; }
|
||||
|
||||
public string CompanyNameEn { get; set; }
|
||||
public string CompanyAddress { get; set; }
|
||||
public Permission Permission { get; set; }
|
||||
public List<AuthOperation> AuthOperation { get; set; }
|
||||
public bool Deleted { get; set; }
|
||||
//密码
|
||||
public string Password { get; set; }
|
||||
|
||||
public bool IsSuperAdmin { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user