Pingfederate opentoken模块CORS请求返回302,而不是200
Pingfederate opentoken module CORS request returns 302 instead of 200
我们使用Ping Federate来保护两个web服务器(两个IIS都使用IIS集成工具包或Ping的opentoken模块进行保护)。一个服务器托管一个WEB API应用程序,另一个托管一个网页。Web API应用程序已启用CORS。
该网页使Ajax将带有json数据的请求发布到API服务器。这会导致浏览器启动飞行前选项请求。在API服务器上,Ping模块拦截这个不包含凭据的请求(规范说预飞选项请求不应该包含凭据),并在Web API代码可以处理它之前返回302重定向,而Web应该返回200。
我目前唯一的猜测是制作一个处理选项请求的自定义模块,并将其安装在opentoken模块之前。还有其他可能/更好的解决方案吗?
我没有等待PING,而是在他们的.NET集成工具包/代理上放了一个IAuthorizationFilter。像这样的自定义过滤器的好处是,您可以对API端点的安全要求有更多的控制。
在编写过滤器时,我使用了以下参考:
- http://www.asp.net/web-api/overview/security/authentication-filters
-
https://msdn.microsoft.com/en-us/magazine/dn781361.aspx
使用opentoken;使用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{公共类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; } }
}
这是PING Federate IIS代理/集成工具包实现的错误吗?
我同意目前W3C的建议(https://www.w3.org/TR/cors/#preflight-request)明确表示在飞行前/选项请求中排除用户凭据。因此,OPTIONS请求应允许匿名请求。得到一个指向身份提供商(IdP)的302,对我来说,它没有遵循建议。
(这只对PING服务器本身有帮助,集成工具包仍然需要允许匿名OPTIONS请求。)Ping Federate在jetty配置文件中返回了更多配置设置:
<security-constraint>
<web-resource-collection>
<web-resource-name>Disable TRACE OPTIONS HEAD</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>TRACE</http-method>
<http-method>OPTIONS</http-method>
</web-resource-collection>
<auth-constraint/>
</security-constraint>
- 节点导出返回一个空对象
- ES6构造函数返回基类的实例
- 监视函数从服务返回不起作用,但作用域函数起作用
- 控制台返回var不是't定义,但它是
- 从函数返回角度承诺
- Javascript返回值只在循环中返回一次
- 从控制器返回后Ajax启动事件激发
- CKFinder 3为所选文件返回错误的URL
- 如何在d3.js中返回路径的y坐标
- 如何从jquery函数返回变量
- Angular js-返回一个包含类似
- JSONP请求返回结果,但也触发error_callback
- 如何使用Spring MVC将Facebook返回的响应数据保存在Java类中
- 从HTTPGET返回一个自定义对象列表,以便在Angular 2应用程序中使用
- JS验证ajax返回的html中的表单数据
- 使用谷歌应用程序脚本将服务器端数据表返回到客户端
- AJAX:$_GET不返回任何值
- 从Javascript方法返回全局变量
- Meteor方法在客户端返回null,在客户端运行的相同方法返回正确的值
- Pingfederate opentoken模块CORS请求返回302,而不是200