grails - 带有 SAML 的 Grails 3 - 身份验证失败
问题描述
我使用 Grails Spring Security SAML Plugin (v3.3.0)创建了一个 Grails (v3.3.6) Web 应用程序。不幸的是,我无法正确配置它。这是针对一个名为“coworkers”的项目,因此您会看到在不同的地方(如下)引用了该名称。我们使用 PingFederate 进行 SAML 身份验证。
问题:身份验证似乎在 PingFederate 端工作,但随后浏览器被发送到无限循环,在我的应用程序和 PingFederate 之间来回切换(更新:无限循环已修复,但问题的根源仍然存在)。日志指示 a MetadataProviderException
(请参阅下面的堆栈跟踪的末尾)。
任何帮助深表感谢!
这是我的application.yml
配置文件的一部分:
---
grails:
plugin:
springsecurity:
saml:
active: true # false does not work as of saml plugin v3.3.0
afterLoginUrl: '/'
afterLogoutUrl: '/'
responseSkew: 300
signatureAlgorithm: 'rsa-sha256'
digestAlgorithm: 'sha256'
userGroupAttribute: 'roles'
autoCreate:
active: false # If you want the plugin to generate users in the DB as they are authenticated via SAML
key: 'id'
assignAuthorities: false # If you want the plugin to assign the authorities that come from the SAML message
metadata:
defaultIdp: 'fed.saml2' # 'coworkers' # @see https://github.com/jeffwils/grails-spring-security-saml/issues/34#issuecomment-396524285
url: '/saml/metadata'
providers:
ping: 'security/idp.xml'
sp:
file: 'security/sp.xml'
defaults:
local: false
entityId: 'coworkers'
alias: 'coworkers'
securityProfile: 'metaiop' # 'pkix' or 'metaiop'
signingKey: 'coworkers'
encryptionKey: 'coworkers'
tlsKey: 'coworkers'
requireArtifactResolveSigned: false
requireLogoutRequestSigned: false
requireLogoutResponseSigned: false
keyManager:
storeFile: 'classpath:security/mykeystore.jks'
storePass: 'mypassword'
passwords:
coworkers: 'mypassword'
defaultKey: ''
这是我的sp.xml
文件:
<?xml version="1.0" encoding="UTF-8"?>
<md:EntityDescriptor entityID="coworkers" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">
<md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:Extensions>
<idpdisco:DiscoveryResponse xmlns:idpdisco="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Location="http://myserver/login/auth/alias/coworkers?disco=false"/>
</md:Extensions>
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>CERTIFICATEREMOVED</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://myserver/saml/SingleLogout/alias/coworkers"/>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://myserver/saml/SingleLogout/alias/coworkers"/>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://myserver/saml/SingleLogout/alias/coworkers"/>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName</md:NameIDFormat>
<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://myserver/saml/SSO/alias/coworkers" index="0" isDefault="true"/>
<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="http://myserver/saml/SSO/alias/coworkers" index="1" isDefault="false"/>
<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:PAOS" Location="http://myserver/saml/SSO/alias/coworkers" index="2" isDefault="false"/>
</md:SPSSODescriptor>
</md:EntityDescriptor>
这是我的idp.xml
文件:
<?xml version="1.0"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="byhfqDHEyvF6TnZ1-nhQEyP0.kQ" cacheDuration="PT1440M" entityID="fed.saml2">
<md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol" WantAuthnRequestsSigned="true">
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>CERTIFICATEREMOVED</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://fed/idp/SSO.saml2"/>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://fed/idp/SSO.saml2"/>
</md:IDPSSODescriptor>
</md:EntityDescriptor>
这是来自日志的堆栈跟踪:
2018-07-13 14:29:00.184 [] DEBUG --- [p-nio-80-exec-3] o.s.security.saml.SAMLProcessingFilter : Authentication request failed: org.springframework.security.authentication.AuthenticationServiceException: Error determining metadata contracts
org.springframework.security.authentication.AuthenticationServiceException: Error determining metadata contracts
at org.springframework.security.saml.SAMLProcessingFilter.attemptAuthentication(SAMLProcessingFilter.java:94)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.saml.metadata.MetadataDisplayFilter.doFilter(MetadataDisplayFilter.java:84)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.saml.SAMLEntryPoint.doFilter(SAMLEntryPoint.java:103)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at grails.plugin.springsecurity.web.SecurityRequestHolderFilter.doFilter(SecurityRequestHolderFilter.groovy:58)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1468)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.opensaml.saml2.metadata.provider.MetadataProviderException: No local entity found for alias coworkers, verify your configuration.
at org.springframework.security.saml.context.SAMLContextProviderImpl.populateLocalEntityId(SAMLContextProviderImpl.java:279)
at org.springframework.security.saml.context.SAMLContextProviderImpl.getLocalEntity(SAMLContextProviderImpl.java:106)
at org.springframework.security.saml.SAMLProcessingFilter.attemptAuthentication(SAMLProcessingFilter.java:79)
... 50 common frames omitted
解决方案
我可以在 application.yml 中看到您将“entityId”提到为“ https://coworkers/ ”,但在您的 SP 元数据文件中 entityId 是“ http://myserver/coworkers ”。使它们都相同,然后重试。
推荐阅读
- excel - 使用 Analysis Services 表格模型进行透视时,数据透视表变慢
- c# - 继承取决于计算的属性
- linux - Systemd 自动化——通过服务在启动时运行 Python 脚本
- angular - 生成字符串响应并在 Angular 应用程序中显示该响应的 Spring Boot 端点
- regex - 简单的常规替换列表中的所有正则表达式
- ionic4 - 在离子加载控制器中显示加载项
- sql - 如何使用 SQL Developer 提供的“技巧”将每个表从特定用户转换为 JSON 格式
- javascript - js-cookie 的 Cookies.get 函数在重置后返回旧值
- python - 无法将 python 文件(包含硒)转换为 exe
- javascript - 如何在stimulus.js中获取元素的类