如何解决Windows Service向ABP Framework API发送请求失败问题
问题:Windows Service调用ABP Framework OAuth2授权API失败
我需要开发一个Windows Service,向ABP Framework的API发送数据。该API采用OAuth2授权验证,需登录后才能访问。我先开发了控制台应用,能正常完成登录并调用API;但使用nssm.exe将其转为Windows Service后,无法正常运行。我认为这和Windows Service的访问限制有关。
1) ConsoleServerApplication代码
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using RestSharp; using RestSharp.Authenticators.OAuth2; using System.Net; using System.Text; namespace NewServerProject { public class Program { static async Task Main(string[] args) { using var listener = new HttpListener(); listener.Prefixes.Add("http://localhost:8001/"); listener.Start(); while (true) { var context = listener.GetContext(); var request = context.Request; if (request.HttpMethod == "POST") { await PostRequestFromGate(request, context); context.Response.Close(); } } } static async Task PostRequestFromGate(HttpListenerRequest request, HttpListenerContext context) { string text; using (var reader = new StreamReader(request.InputStream, request.ContentEncoding)) { text = reader.ReadToEnd(); } await PostRequestToAPI(text); } static async Task PostRequestToAPI(string text) { string clientId = "CM_Postman"; string clientSecret = "3284687Egor"; string redirectUri = "https://localhost:44318/swagger/oauth2-redirect.html"; string authorizationEndpoint = "https://localhost:44350/connect/authorize"; string scope = "TestProject"; string tokenEndpoint = "https://localhost:44350/connect/token"; string authorizationCode = GetAuthorizationCode(authorizationEndpoint, clientId, redirectUri, scope); string accessTokfen = GetAuthToken(tokenEndpoint, clientId, clientSecret, authorizationCode, redirectUri); await GetData(accessTokfen, text); } static string GetAuthorizationCode(string authorizationEndpoint, string clientId, string redirectUri, string scope) { string authorizationUrl = $"{authorizationEndpoint}?client_id={clientId}&redirect_uri={redirectUri}&scope={scope}&response_type=code"; return PostToSupportApp(authorizationUrl).Result; } public record JsonClass(string url); static async Task<string> PostToSupportApp(string url) { JsonClass jsonClass = new(url); string jsonString = JsonConvert.SerializeObject(jsonClass); var client = new RestClient("http://localhost:8003/"); var request = new RestRequest() { Method = Method.Post }; request.AddHeader("Content-Type", "application/json"); request.AddHeader("Accept", "application/json"); request.AddParameter("application/json", jsonString, ParameterType.RequestBody); RestResponse response = client.Execute(request); foreach (var f in response.Headers) { if (f.Name.ToString() == "code") { return f.Value.ToString(); } } return null; } public record Token(string access_token, string token_type, int expires_in, string scope); static string GetAuthToken(string tokenEndpoint, string clientId, string clientSecret, string authorizationCode, string redirectUri) { var client = new RestClient(tokenEndpoint); var request = new RestRequest() { Method = Method.Post }; request.AddParameter("grant_type", "authorization_code"); request.AddParameter("code", authorizationCode); request.AddParameter("redirect_uri", redirectUri); request.AddParameter("username", "admin"); request.AddParameter("password", "1q2w3E*"); request.AddParameter("client_id", clientId); request.AddParameter("client_secret", clientSecret); RestResponse response = client.Execute(request); Token token = System.Text.Json.JsonSerializer.Deserialize<Token>(response.Content.ToString()); // Extract and return the access token return token.access_token; } static async Task GetData(string accesToken, string jsodata) { string apiEndpoint = "https://localhost:44318/api/app/check-ins/datanew"; var authenticator = new OAuth2AuthorizationRequestHeaderAuthenticator( accesToken, "Bearer" ); var options = new RestClientOptions(apiEndpoint) { Authenticator = authenticator }; var client = new RestClient(options); var request = new RestRequest() { Method = Method.Post }; request.AddJsonBody(jsodata); RestResponse response = client.Execute(request); } } }
2) SupportConsoleApp说明
由于Windows Service没有界面,且通过它打开应用并非最佳实践,我创建了3个辅助应用用于获取令牌所需的CODE:
- 获取CODE需要先完成登录,授权成功后会收到包含CODE的跳转链接
- 我通过网页抓取从链接中提取CODE,再发送至ConsoleServerApplication
有没有人知道如何解决这个问题?
内容的提问来源于stack exchange,提问作者Egor
相关产品推荐
相关产品推荐

