使用pac4j-saml,如何根据shiro.ini设置获取sp元数据

时间:2016-04-29 20:32:50

标签: java apache saml cas shiro

我需要在EAR应用程序中创建的各种WAR中执行SSO。我按照这里提供的演示https://github.com/pac4j/buji-pac4j-demo并在EAR中的每个WAR中配置了每个shiro.ini,其方式与演示中提供的完全相同。我正在使用资源:samlKeystore.jks(具有相同的凭据)并尝试使用相同的okta(resource:metadata-okta.xml)IDP进行连接。但是,当我点击“受SAML保护的URL:saml / index.jsp”链接时,出现此错误:

2016-04-29 16:20:11,460 ERROR [io.undertow.request](默认任务-13)UT005023:对/MyWebA/saml/index.jsp的异常处理请求:javax.servlet.ServletException:org。 pac4j.s​​aml.exceptions.SAMLException:Keystore没有私钥     在org.apache.shiro.web.servlet.AdviceFilter.cleanup(AdviceFilter.java:196)     在org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:148)

...

引起:org.pac4j.s​​aml.exceptions.SAMLException:Keystore没有私钥     在org.pac4j.s​​aml.crypto.KeyStoreCredentialProvider.getPrivateKeyAlias(KeyStoreCredentialProvider.java:175)     在org.pac4j.s​​aml.crypto.KeyStoreCredentialProvider。(KeyStoreCredentialProvider.java:98)     在org.pac4j.s​​aml.crypto.KeyStoreCredentialProvider。(KeyStoreCredentialProvider.java:105)

这很奇怪,因为我在resources文件夹中实际有samlKeystore.jks。

我的问题是:

1)为什么即使我使用演示附带的同一个密钥库,我也会收到“Keystore没有私钥”的问题?顺便说一句,按原样运行演示没有这个问题。

2)我是否想自己配置IDP,我需要一个描述我的EAR应用程序的SP元数据。我注意到shiro.ini将此配置设置为:saml2Config.serviceProviderMetadataPath = resource:sp-metadata.xml。但我可以找到sp-metadata.xml(如果它意味着生成一个)。如何使用shiro.ini生成sp-metadata.xml?由于我使用的是buji-pac4j和pac4j-saml,我无法弄清楚如何使用此处描述的2个选项https://github.com/pac4j/pac4j/wiki/Clients#saml-support

编辑包含pom.xml和shiro.ini

     <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <parent>
        <groupId>MyEARProject</groupId>
        <artifactId>MyEARProject</artifactId>
        <version>0.0.1-SNAPSHOT</version>
      </parent>
      <groupId>MyEAR</groupId>
      <artifactId>MyEAR</artifactId>
      <packaging>ear</packaging>  
        <properties>
            <mywebversion>0.0.2</mywebversion>
            <pac4jVersion>1.8.8</pac4jVersion>
            <bujiVersion>1.4.2</bujiVersion>
            <javaVersion>1.8</javaVersion>
        </properties>   
      <dependencies>    
            <dependency>
                <groupId>io.buji</groupId>
                <artifactId>buji-pac4j-servlet</artifactId>
                <version>${bujiVersion}</version>
            </dependency>
            <dependency>
                <groupId>org.pac4j</groupId>
                <artifactId>pac4j-oauth</artifactId>
                <version>${pac4jVersion}</version>
            </dependency>
            <dependency>
                <groupId>org.pac4j</groupId>
                <artifactId>pac4j-openid</artifactId>
                <version>${pac4jVersion}</version>
            </dependency>
            <dependency>
                <groupId>org.pac4j</groupId>
                <artifactId>pac4j-cas</artifactId>
                <version>${pac4jVersion}</version>
            </dependency>
            <dependency>
                <groupId>org.pac4j</groupId>
                <artifactId>pac4j-http</artifactId>
                <version>${pac4jVersion}</version>
            </dependency>
            <dependency>
                <groupId>org.pac4j</groupId>
                <artifactId>pac4j-saml</artifactId>
                <version>${pac4jVersion}</version>
            </dependency>
            <dependency>
                <groupId>org.pac4j</groupId>
                <artifactId>pac4j-oidc</artifactId>
                <version>${pac4jVersion}</version>
            </dependency>
            <dependency>
                <groupId>org.pac4j</groupId>
                <artifactId>pac4j-gae</artifactId>
                <version>${pac4jVersion}</version>
            </dependency>
            <dependency>
                <groupId>org.pac4j</groupId>
                <artifactId>pac4j-ldap</artifactId>
                <version>${pac4jVersion}</version>
            </dependency>
            <dependency>
                <groupId>org.pac4j</groupId>
                <artifactId>pac4j-sql</artifactId>
                <version>${pac4jVersion}</version>
            </dependency>
            <dependency>
                <groupId>org.pac4j</groupId>
                <artifactId>pac4j-mongo</artifactId>
                <version>${pac4jVersion}</version>
            </dependency>
            <dependency>
                <groupId>org.pac4j</groupId>
                <artifactId>pac4j-stormpath</artifactId>
                <version>${pac4jVersion}</version>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>1.0.13</version>
            </dependency>

            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>3.0.1</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>javax.servlet.jsp</groupId>
                <artifactId>jsp-api</artifactId>
                <version>2.2</version>
                <scope>provided</scope>
            </dependency>
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache-core</artifactId>
            <version>2.5.0</version>
        </dependency>
        <dependency>
             <groupId>org.apache.shiro</groupId>
             <artifactId>shiro-ehcache</artifactId>
             <version>1.2.4</version>
             <scope>provided</scope>
        </dependency    
            <dependency>
                <groupId>com.my</groupId>
                <artifactId>webApp1</artifactId>
                <version>${mywebversion}</version>
                <type>war</type>
            </dependency>
            <dependency>
                <groupId>com.my</groupId>
                <artifactId>webAppRest</artifactId>
                <version>${mywebversion}</version>
                <type>war</type>
            </dependency>
            <dependency>
                <groupId>com.my</groupId>
                <artifactId>webApp2</artifactId>
                <version>${mywebversion}</version>
                <type>war</type>
            </dependency>
      </dependencies> 
    </project>

这是我的shiro.ini配置

[main]
############################################################################
# PROVIDERS :
############################################################################
#sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
#sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
#sessionManager.sessionDAO = $sessionDAO
#cookie = org.apache.shiro.web.servlet.SimpleCookie
#cookie.name = SSOcookie
#cookie.path = /
#cookie.domain = localhost
#sessionManager.sessionIdCookie = $cookie
#securityManager.sessionManager = $sessionManager
#cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
#cacheManager.cacheManagerConfigFile = classpath:ehcache.xml
#securityManager.cacheManager = $cacheManager
#securityManager.sessionMode = native
#Para testing:
#ssl.enabled=false    
subjectFactory = io.buji.pac4j.ClientSubjectFactory
securityManager.subjectFactory = $subjectFactory    
facebookClient = org.pac4j.oauth.client.FacebookClient
facebookClient.key = 145278422258960
facebookClient.secret = be21409ba8f39b5dae2a7de525484da8    
twitterClient = org.pac4j.oauth.client.TwitterClient
twitterClient.key = CoxUiYwQOSFDReZYdjigBA
twitterClient.secret = 2kAzunH5Btc4gRSaMr7D7MkyoJ5u1VzbOOzE8rBofs    
simpleAuthenticator = org.pac4j.http.credentials.authenticator.test.SimpleTestUsernamePasswordAuthenticator    
formClient = org.pac4j.http.client.indirect.FormClient
formClient.loginUrl = http://localhost:8080/webApp1/loginForm.jsp
formClient.authenticator = $simpleAuthenticator    
basicAuthClient = org.pac4j.http.client.indirect.IndirectBasicAuthClient
basicAuthClient.authenticator = $simpleAuthenticator    
casClient = org.pac4j.cas.client.CasClient
casClient.casLoginUrl = https://casserverpac4j.herokuapp.com
#casClient.gateway=true    
vkClient = org.pac4j.oauth.client.VkClient
vkClient.key = 4224582
vkClient.secret = nDc4IHTqu8ioFMkHKifq    
saml2Config = org.pac4j.saml.client.SAML2ClientConfiguration
saml2Config.keystorePath = resource:samlKeystore.jks
saml2Config.keystorePassword = pac4j-demo-passwd
saml2Config.privateKeyPassword = pac4j-demo-passwd
saml2Config.identityProviderMetadataPath = resource:metadata-okta.xml
saml2Config.maximumAuthenticationLifetime = 3600
saml2Config.serviceProviderEntityId = http://localhost:8080/webApp1/callback?client_name=SAML2Client
saml2Config.serviceProviderMetadataPath = resource:sp-metadata.xml    
saml2Client = org.pac4j.saml.client.SAML2Client
saml2Client.configuration = $saml2Config    
clients = org.pac4j.core.client.Clients
clients.callbackUrl = http://localhost:8080/webApp1/callback
clients.clients = $facebookClient,$twitterClient,$formClient,$basicAuthClient,$casClient,$vkClient,$saml2Client    
############################################################################
# REALM & FILTERS :
############################################################################
clientsRealm = io.buji.pac4j.ClientRealm
clientsRealm.defaultRoles = ROLE_USER
clientsRealm.clients = $clients    
clientsFilter = io.buji.pac4j.ClientFilter
clientsFilter.clients = $clients
clientsFilter.failureUrl = /error500.jsp    
facebookRoles = io.buji.pac4j.filter.ClientRolesAuthorizationFilter
facebookRoles.client = $facebookClient
twitterRoles = io.buji.pac4j.filter.ClientRolesAuthorizationFilter
twitterRoles.client = $twitterClient
formRoles = io.buji.pac4j.filter.ClientRolesAuthorizationFilter
formRoles.client = $formClient
basicAuthRoles = io.buji.pac4j.filter.ClientRolesAuthorizationFilter
basicAuthRoles.client = $basicAuthClient
casRoles = io.buji.pac4j.filter.ClientRolesAuthorizationFilter
casRoles.client = $casClient
vkRoles = io.buji.pac4j.filter.ClientRolesAuthorizationFilter
vkRoles.client = $vkClient
saml2Roles = io.buji.pac4j.filter.ClientRolesAuthorizationFilter
saml2Roles.client = $saml2Client    
[urls]
/facebook/** = facebookRoles[ROLE_USER]
/twitter/** = twitterRoles[ROLE_USER]
/form/** = formRoles[ROLE_USER]
/basicauth/** = basicAuthRoles[ROLE_USER]
/cas/** = casRoles[ROLE_USER]
/vk/** = vkRoles[ROLE_USER]
/saml/** = saml2Roles[ROLE_USER]
/callback = clientsFilter
/logout = logout
/** = anon

由于我想在我的EAR中的各种WAR中执行SSO,我最初添加了EhCacheManager,但后来我收到了以下错误。

2016-05-01 22:03:38,126 INFO  [org.apache.shiro.web.env.EnvironmentLoader] (ServerService Thread Pool -- 163) Starting Shiro environment initialization.
2016-05-01 22:03:38,179 ERROR [org.apache.shiro.web.env.EnvironmentLoader] (ServerService Thread Pool -- 163) Shiro environment initialization failed: org.apache.shiro.config.ConfigurationException: Unable to instantiate class [org.apache.shiro.cache.ehcache.EhCacheManager] for object named 'cacheManager'.  Please ensure you've specified the fully qualified class name correctly.
    at org.apache.shiro.config.ReflectionBuilder.createNewInstance(ReflectionBuilder.java:151)
    at org.apache.shiro.config.ReflectionBuilder.buildObjects(ReflectionBuilder.java:119)
    at org.apache.shiro.config.IniSecurityManagerFactory.buildInstances(IniSecurityManagerFactory.java:161)
    at org.apache.shiro.config.IniSecurityManagerFactory.createSecurityManager(IniSecurityManagerFactory.java:124)
    at org.apache.shiro.config.IniSecurityManagerFactory.createSecurityManager(IniSecurityManagerFactory.java:102)
    at org.apache.shiro.config.IniSecurityManagerFactory.createInstance(IniSecurityManagerFactory.java:88)
    at org.apache.shiro.config.IniSecurityManagerFactory.createInstance(IniSecurityManagerFactory.java:46)
    at org.apache.shiro.config.IniFactorySupport.createInstance(IniFactorySupport.java:123)
    at org.apache.shiro.util.AbstractFactory.getInstance(AbstractFactory.java:47)
    at org.apache.shiro.web.env.IniWebEnvironment.createWebSecurityManager(IniWebEnvironment.java:203)
    at org.apache.shiro.web.env.IniWebEnvironment.configure(IniWebEnvironment.java:99)
    at org.apache.shiro.web.env.IniWebEnvironment.init(IniWebEnvironment.java:92)
    at org.apache.shiro.util.LifecycleUtils.init(LifecycleUtils.java:45)
    at org.apache.shiro.util.LifecycleUtils.init(LifecycleUtils.java:40)
    at org.apache.shiro.web.env.EnvironmentLoader.createEnvironment(EnvironmentLoader.java:221)
    at org.apache.shiro.web.env.EnvironmentLoader.initEnvironment(EnvironmentLoader.java:133)
    at org.apache.shiro.web.env.EnvironmentLoaderListener.contextInitialized(EnvironmentLoaderListener.java:58)
    at io.undertow.servlet.core.ApplicationListeners.contextInitialized(ApplicationListeners.java:187)
    at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:198)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.startContext(UndertowDeploymentService.java:100)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentService$1.run(UndertowDeploymentService.java:82)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
    at org.jboss.threads.JBossThread.run(JBossThread.java:320)
Caused by: org.apache.shiro.util.UnknownClassException: Unable to load class named [org.apache.shiro.cache.ehcache.EhCacheManager] from the thread context, current, or system/application ClassLoaders.  All heuristics have been exhausted.  Class could not be found.
    at org.apache.shiro.util.ClassUtils.forName(ClassUtils.java:148)
    at org.apache.shiro.util.ClassUtils.newInstance(ClassUtils.java:164)
    at org.apache.shiro.config.ReflectionBuilder.createNewInstance(ReflectionBuilder.java:144)
    ... 26 more

Buji-pac4j是否使用带有WAR的SSO的EhCache配置?

2 个答案:

答案 0 :(得分:0)

1)我从未遇到过这个错误,看起来很奇怪。你能尝试使用最新的pac4j-saml版本,我的意思是1.8.8,其中私钥选择算法有所改进吗?

2)SP元数据是根据您定义的SAML2Configuration生成的,并且基于serviceProviderMetadataPath属性定位。更改SAML2Configuration以生成适当的配置

答案 1 :(得分:0)

对于(2),我发现在处理sAML请求时,在shiro.ini的[main]部分中设置以下条目将在Web项目的根文件夹中生成文件“ sp-metadata.xml”。 :

saml2Config.serviceProviderMetadataPath = sp-metadata.xml
saml2Config.forceServiceProviderMetadataGeneration = true

对于(1),听起来好像没有密钥库放置在类路径中。我发现了一个侧面说明:我的项目对待资源文件夹与src文件夹的不同之处在于它过滤了资源。这破坏了密钥库,直到我将密钥库移到src文件夹。