2

Ping Federate を使用して 2 つの Web サーバーを保護しています (IIS と、IIS 統合キットまたは Ping の opentoken モジュールを使用して保護されている両方)。1 つのサーバーは WEB API アプリケーションをホストし、もう 1 つのサーバーは Web ページをホストします。Web API アプリケーションでは CORS が有効になっています。

Web ページは、JSON データを含む Ajax ポスト リクエストを API サーバーに送信します。これにより、ブラウザはプリフライト オプション リクエストを開始します。API サーバーでは、Ping モジュールは資格情報を含まないこの要求をインターセプトし (仕様では、プリフライト オプション要求には資格​​情報が含まれていないとされています)、200 を返す必要がある場合に、Web API コードがそれを処理できるようになる前に 302 リダイレクトを返します。 .

私の唯一の推測は、オプション要求を処理するカスタム モジュールを作成し、それを opentoken モジュールの前にインストールすることです。他に考えられる/より良い解決策はありますか?

4

2 に答える 2

2

PING を待つ代わりに、.NET Integration Kit/Agent の上に IAuthorizationFilter を配置しました。このようなカスタム フィルターの良い点は、API エンドポイントのセキュリティ要件をより詳細に制御できることです。

フィルターを作成するときは、次のリファレンスを使用しました。

  • http://www.asp.net/web-api/overview/security/authentication-filters
  • https://msdn.microsoft.com/en-us/magazine/dn781361.aspx

    オープントークンの使用; PF.SAML.Result を使用します。システムを使用する; System.Collections.Generic の使用; System.Configuration を使用します。System.Linq を使用します。System.Net.Http の使用; System.Net.Http.Headers の使用; System.Security.Claims の使用; System.Text を使用します。System.Threading の使用; System.Threading.Tasks の使用; System.Web.Http.Filters の使用;

    名前空間 PF.SAML.Filters { public class PingAuthenticationAttribute : IAuthenticationFilter { public bool AllowMultiple { get { return false; } }

        // http://www.asp.net/web-api/overview/security/authentication-filters
        // https://msdn.microsoft.com/en-us/magazine/dn781361.aspx
        public async Task AuthenticateAsync( HttpAuthenticationContext context, CancellationToken cancellationToken )
        {
            await Task.Run( () => {
                /*
                 * Look for credentials in the request.
                 * If there are no credentials, do nothing and return (no-op).
                 * If there are credentials but the filter does not recognize the authentication scheme, do nothing and return (no-op). Another filter in the pipeline might understand the scheme.
                 * If there are credentials that the filter understands, try to authenticate them.
                 * If the credentials are bad, return 401 by setting context.ErrorResult.
                 * If the credentials are valid, create an IPrincipal and set context.Principal.
                 */
                var opentoken = context.Request.Headers.GetCookies()
                    .SelectMany( c => c.Cookies )
                    .Where( c => c.Name == "opentoken" )
                    .FirstOrDefault();
    
                if( opentoken == null ) return;
    
                var userInfo = getOpenToken( opentoken.Value );
    
                if( userInfo == null ) {
                    context.ErrorResult = new AuthenticationFailureResult( "Invalid Token", context.Request );
                    return;
                }
    
                var claims = new List<Claim>();
                foreach( var item in userInfo ) {
                    foreach( var value in userInfo[item.Key] ) {
                        claims.Add( new Claim( item.Key, value ) );
                    }
                }
    
                var id = new ClaimsIdentity( claims, "opentoken" );
                var principle = new ClaimsPrincipal( new[] { id } );
    
                context.Principal = principle;
    
            } );
        }
    
        public async Task ChallengeAsync( HttpAuthenticationChallengeContext context, CancellationToken cancellationToken )
        {
            await Task.Run( () => {
                var challenge = new AuthenticationHeaderValue( "SAML" );
                context.Result = new AddChallengeOnUnauthorizedResult( challenge, context.Result );
            } );
        }
    
    
        private MultiStringDictionary getOpenToken( string token )
        {
            MultiStringDictionary attributes = null;
    
            Configuration.Agent agentConfig = (Configuration.Agent) ConfigurationManager.GetSection( "pfConfigurationGroup/agentConfiguration" ); 
            AgentConfiguration config = new AgentConfiguration
            {
                CookieDomain = agentConfig.CookieDomain,
                CookiePath = agentConfig.CookiePath,
                NotBeforeTolerance = agentConfig.NotBeforeTolerance,
                ObfuscatePassword = agentConfig.ObfuscatePassword,
                RenewUntilLifetime = agentConfig.RenewUntilLifetime,
                SecureCookie = agentConfig.SecureCookie,
                SessionCookie = agentConfig.SessionCookie,
                TokenLifetime = agentConfig.TokenLifetime,
                TokenName = agentConfig.TokenName,
                UseCookie = agentConfig.UseCookie,
                UseSunJCE = agentConfig.UseSunJCE,
                UseVerboseErrorMessages = agentConfig.UseVerboseErrorMessages
            };
    
            var str = ( config.ObfuscatePassword
                ? Encoding.UTF8.GetString( Obfuscator.Deobfuscate( agentConfig.Password ) )
                : Encoding.ASCII.GetString( Convert.FromBase64String( agentConfig.Password ) ) );
            config.SetPassword( str, Token.CipherSuite.AES_128_CBC );
    
            // TODO: Check for token expiration
    
            Agent agent = new Agent( config );
            attributes = agent.ReadTokenMultiStringDictionary( token );
    
            return attributes;
        }
    }
    

    }

于 2016-05-06T16:57:21.617 に答える