用户未登录时HttpClient.GetAsync上的System.IO.IOException

时间:2017-10-15 09:05:01

标签: c# asp.net-core aspnetboilerplate asp.net-core-identity

我正在使用HttpClient为基于ABP的网络服务创建WPF客户端。

当我向未登录的用户使用AbpAuthorizeAttribute注释的某个控制器方法或没有权限的用户发出请求时,我得到了System.IO.IOException

在浏览器中,我得到了这个JSON:

{
    "result": null,
    "targetUrl": null,
    "success": false,
    "error": {
        "code": 0,
        "message": "Current user did not login to the application!",
        "details": null,
        "validationErrors": null
    },
    "unAuthorizedRequest": true,
    "__abp": true
}

当用户登录时,一切正常。 我想在WPF客户端中获得相同的JSON。我做错了什么?

public virtual async Task<TResult> GetAsync<TResult>(string url, int? timeout = null, params NameValue[] urlParameters)
        where TResult : class
{
    var cookieContainer = new CookieContainer();

    using (var handler = new HttpClientHandler { CookieContainer = cookieContainer })
    {
        using (var client = new HttpClient(handler))
        {
            client.Timeout = timeout.HasValue ? TimeSpan.FromMilliseconds(timeout.Value) : Timeout;
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            foreach (var header in RequestHeaders)
            {
                client.DefaultRequestHeaders.Add(header.Name, header.Value);
            }

            foreach (var cookie in Cookies)
            {
                if (!string.IsNullOrEmpty(BaseUrl))
                {
                    cookieContainer.Add(new Uri(BaseUrl), cookie);
                }
                else
                {
                    cookieContainer.Add(cookie);
                }
            }

            var uri = new Uri(BaseUrl).AddPathSegment(url);
            var urlBuilder = new UriBuilder(uri);

            if (urlParameters != null && urlParameters.Any())
            {
                BuildUrlParametersString(urlBuilder, urlParameters);
            }

            using (var response = await client.GetAsync(urlBuilder.Uri)) // <--- Exception here
            {
                SetResponseHeaders(response);
                GenerateExceptionOnBadStatus(response, urlBuilder.ToString());

                var ajaxResponse = JsonString2Object<AjaxResponse<TResult>>(await response.Content.ReadAsStringAsync());

                if (!ajaxResponse.Success)
                {
                    Generateexception(ajaxResponse);
                }

                return ajaxResponse.Result;
            }
        }
    }
}

服务器日志:

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:62114/api/User
info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action PAG.Identity.Web.Api.UsersContoller.GetAll (PAG.Identity.Web.Mvc) in 870.4395ms
fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HL8JLDUTGR59", Request id "0HL8JLDUTGR59:00000001": An unhandled exception was thrown by the application.
Abp.Authorization.AbpAuthorizationException: Текущий пользователь не вошёл в приложение!
   at Abp.Authorization.AuthorizationHelper.<AuthorizeAsync>d__19.MoveNext() in D:\Github\aspnetboilerplate\src\Abp\Authorization\AuthorizationHelper.cs:line 43
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Abp.Authorization.AuthorizationHelper.<CheckPermissions>d__22.MoveNext() in D:\Github\aspnetboilerplate\src\Abp\Authorization\AuthorizationHelper.cs:line 98
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Abp.Authorization.AuthorizationHelper.<AuthorizeAsync>d__20.MoveNext() in D:\Github\aspnetboilerplate\src\Abp\Authorization\AuthorizationHelper.cs:line 57
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Nito.AsyncEx.Synchronous.TaskExtensions.WaitAndUnwrapException(Task task)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Nito.AsyncEx.Synchronous.TaskExtensions.WaitAndUnwrapException(Task task)
   at Nito.AsyncEx.AsyncContext.Run(Func`1 action)
   at Abp.Authorization.AuthorizationInterceptor.Intercept(IInvocation invocation) in D:\Github\aspnetboilerplate\src\Abp\Authorization\AuthorizationInterceptor.cs:line 20
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Microsoft.AspNetCore.Mvc.Controller.Dispose()
   at Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.ApplyConcerns(IEnumerable`1 steps, Object instance)
   at Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.Destroy(Object instance)
   at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.Release(Object instance)
   at Castle.MicroKernel.Burden.Release()
   at Castle.MicroKernel.Releasers.LifecycledComponentsReleasePolicy.Release(Object instance)
   at Castle.Windsor.MsDependencyInjection.MsLifetimeScope.DisposeInternal() in D:\Github\castle-windsor-ms-adapter\src\Castle.Windsor.MsDependencyInjection\MsLifeTimeScope.cs:line 108
   at Microsoft.AspNetCore.Hosting.Internal.RequestServicesFeature.Dispose()
   at Microsoft.AspNetCore.Hosting.Internal.RequestServicesContainerMiddleware.<Invoke>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Frame`1.<ProcessRequestsAsync>d__2.MoveNext()
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 1055.3429ms 401 application/json; charset=utf-8

更新

我认为问题是因为我的控制器使用了AbpAuthorize而不是AbpMvcAuthorize属性。现在问题是:我在未经授权的请求中得到302然后是404。我认为这是因为Identity使用AutomaticChallenge设置身份验证,但我不知道如何禁用它。

1 个答案:

答案 0 :(得分:0)

ASP.NET Core 1.x

ABP v2.x / module-zero-core-template v2.x

修改。核心项目中的IdentityRegistrar

// Before
services.AddAbpIdentity<Tenant, User, Role>()

// After
services.AddAbpIdentity<Tenant, User, Role>(options =>
{
    options.Cookies.ApplicationCookie.AutomaticChallenge = false;
})

参考:https://github.com/aspnet/Security/issues/804

ASP.NET Core 2.0

ABP v3.x / module-zero-core-template v3.0.0 - v3.4.0

修改 .Web.Host 项目中的AuthConfigurer

// Before
services.AddAuthentication()

// After
services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = "JwtBearer";
    options.DefaultChallengeScheme = "JwtBearer";
})

参考:module-zero-core-template v3.5.0中的92b6270