javascript - Pingfederate opentoken 模块 CORS 请求返回 302 而不是 200

标签 javascript cors iis-7.5 pingfederate preflight

我们使用 Ping Federate 来保护两个 Web 服务器(都是 IIS,并且都使用 IIS 集成套件或 Ping 的 opentoken 模块进行保护)。一台服务器托管 WEB API 应用程序,另一台服务器托管网页。 Web API 应用程序已启用 CORS。

网页使用 json 数据向 API 服务器发出 Ajax post 请求。这会导致浏览器发起预检选项请求。在 API 服务器上,Ping 模块会拦截此不包含凭据的请求(规范规定预检选项请求不应包含凭据),并在 Web API 代码应该返回 200 时在处理该请求之前返回 302 重定向。 .

我当前唯一的猜测是制作一个处理选项请求的自定义模块并将其安装在 opentoken 模块之前。还有其他可能/更好的解决方案吗?

最佳答案

我没有等待 PING,而是在其 .NET 集成套件/代理之上放置了 IAuthorizationFilter。像这样的自定义过滤器的好处是您可以更好地控制 API 端点的安全要求。

在编写过滤器时,我使用了以下引用文献:

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

    使用开放 token ; 使用 PF.SAML.Result; 使用系统; 使用 System.Collections.Generic; 使用系统配置; 使用 System.Linq; 使用 System.Net.Http; 使用 System.Net.Http.Headers; 使用 System.Security.Claims; 使用系统文本; 使用系统线程; 使用 System.Threading.Tasks; 使用 System.Web.Http.Filters;

    命名空间 PF.SAML.Filters { 公共(public)类 PingAuthenticationAttribute :IAuthenticationFilter { 公共(public) bool AllowMultiple { 获取{ 返回 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;
        }
    }
    

    }

关于javascript - Pingfederate opentoken 模块 CORS 请求返回 302 而不是 200,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36658253/

相关文章:

javascript - XMLHttpRequest无法加载XXX No'Access-Control-Allow-Origin' header

javascript - Firebase 云功能 - onCall 不起作用

c# - HttpListener 的 CORS 访问

asp.net-mvc-4 - 如何使用 web.config 设置自定义标题?

javascript - CSS 使用 css 类和 javascript 查找父级的 sibling

javascript - 如何在 JavaScript 中存储 Firebase 数据库值?

javascript - 定义的 var 为 null (document.getElementById ('existingDiv' ))

javascript - 用于大量数据的 WebSockets 与 XHR

iis-7.5 - 如何分配 IIS_IUSRS

asp.net - 在 IIS 7.5 下工作的 web.config 在 IIS 10 下不起作用