先请求授权失败,然后正确

问题描述 投票:0回答:1

在我们的后端,我们有几个需要通信的服务。到目前为止,他们还没有获得任何形式的授权。所以任何人都可以与任何服务进行通信。现在我们想为所有服务引入授权。因此,我们编写了以下

Authorize
-属性:

   public class BackendServiceAuthorizationAttribute : AuthorizeAttribute
   {
       private static readonly Lazy<UserAuthorizationProvider> lazyUserAuthorizationProvider =
           new Lazy<UserAuthorizationProvider>(() => new UserAuthorizationProvider(), true);

       private static UserAuthorizationProvider authorizationProvider => lazyUserAuthorizationProvider.Value;

       public override void OnAuthorization(HttpActionContext actionContext)
       {
           if (actionContext == null)
               throw new ArgumentNullException(nameof(actionContext));

           if (!IsAuthorized(actionContext))
           {
               EventLog.WriteEntry($"Backend-System", "Unauthorized request", EventLogEntryType.Warning);
               HandleUnauthorizedRequest(actionContext);
           }
           else
           {
               EventLog.WriteEntry($"Backend-System", "Authorized request", EventLogEntryType.Warning);
           }
       }

       protected override bool IsAuthorized(HttpActionContext actionContext)
       {

           if (actionContext == null)
               throw new ArgumentNullException(nameof(actionContext));

           return IsUserInGroup(actionContext) || IsUserAuthorized(actionContext);
       }

       private bool IsUserAuthorized(HttpActionContext actionContext)
       {
           bool isUserAuthenticated = false;

           try
           {
               string currentUserId = DoClean(actionContext.RequestContext.Principal.Identity.Name);

               isUserAuthenticated = authorizationProvider.IsUserAuthenticated(currentUserId);
           }
           catch (Exception e)
           {
               EventLog.WriteEntry($"Backend-System", $"Exception in IsUserAuthorized: {e}\nRequest-Principal: {actionContext.RequestContext.Principal}\nRequest: {actionContext.Request}");

           }

           return isUserAuthenticated;
       }

       private const string SoftwareAdmins = "Backend-Software-Administratoren";
       private const string ServerAdmins = "Backend-Server-Administratoren";


       private bool IsUserInGroup(HttpActionContext actionContext)
       {
           bool isInRole = false;
           try
           {
               isInRole = actionContext.ControllerContext.RequestContext.Principal != null && (
                   actionContext.ControllerContext.RequestContext.Principal.IsInRole(SoftwareAdmins) ||
                   actionContext.ControllerContext.RequestContext.Principal.IsInRole(ServerAdmins));
           }
           catch (Exception e)
           {
               EventLog.WriteEntry($"Backend-System", $"Exception in IsUserInGroup: {e}");
           }


           return isInRole;
       }

       private static string DoClean(string userName)
       {
           string retval = userName;
           if (retval.Contains("\\"))
           {
               string[] retsplits = retval.Split('\\');
               retval = retsplits[retsplits.Length - 1];
           }
           if (retval.Contains("@"))
           {
               string[] retsplits = retval.Split('@');
               retval = retsplits[0];
           }
           return retval.ToUpper();
       }
   }

UserAuthorizationProvider
只是一个允许的用户 ID 初始化一次的类。

在每台服务器上运行服务的用户不是 SoftwareAdmins 或 ServerAdmins 的成员。所以我们点击 IsUserAuthorized-Method。

在每个服务器上的 Windows 事件日志中,我看到 IsUserAuthorized 抛出异常,然后我看到来自

OnAuthorization
的条目,其中写着:
Unauthorized request
。事件日志中的下一个条目是
Authorized request

所以我假设,一个请求会多次调用 Authorize-Attribute。

我想知道是否可以避免这种异常?

在异常消息中,我可以看到

actionContext.RequestContext.Principal
为空,因此对
actionContext.RequestContext.Principal.Identity
的调用会引发异常。在第二个请求中必须填写。

所有服务都提供使用 OWIN 框架托管的自托管 REST-API。服务的配置如下所示:

public void Configuration(IAppBuilder appBuilder)
{

    HttpListener listener = (HttpListener)appBuilder.Properties["System.Net.HttpListener"];
    listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication | AuthenticationSchemes.Anonymous;
    
    HttpConfiguration config = new HttpConfiguration();

    config.DependencyResolver = controllerDependencyResolver;
    
    config.MapHttpAttributeRoutes();

    config.EnsureInitialized();

    appBuilder.UseWebApi(config);
}

使用 REST-API 的

HttpClient
被包装在名为“RestClient”的类中。要创建
RestClient
的实例,我们使用以下代码:

  private RestClient GetRestClient()
  {

      RestClientSettings restClientSettings = RestClientSettings.CreateDefault();
      restClientSettings.UseDefaultCredentials = false;
      ICredential cred = CredentialProvider.GetCredential(CredentialType.BackendSystem);
      restClientSettings.Credentials = new NetworkCredential(cred.GetUserName(), cred.GetPwdSec(), "our_domain");
      RestClient client = new RestClient($"{targetUrl}", restClientSettings);
      return client;
  }

所以我的问题是,为什么第一次尝试授权失败并且

actionContext.RequestContext.Principal
为空?

c# rest owin authorize.net
1个回答
0
投票

我自己解决了。我必须提供

AuthenticationSchemes.Negotiate

© www.soinside.com 2019 - 2024. All rights reserved.