java - CAS 身份验证后获取 JSF Managed Bean 中的 LDAP 属性

标签 java jsf spring-security ldap cas

我正在为我的应用程序使用 CAS 身份验证。我将用户详细信息存储在 LDAP Active Directory 中。我在我的 Web 应用程序中使用 Spring Security 和 JSF。我发现很难将国家/地区、国家/地区代码等 LDAP 属性获取到托管 bean。我能够从 SecurityContext 检索角色、用户名、密码,但无法从 ldap 获取登录用户的国家/地区详细信息。

我相信在 CAS 身份验证之后一定有一种方法,我可以通过 CAS 检索 ldap 属性到 JSF 托管 bean。我尝试了下面的链接,但无法获取托管 bean 的详细信息。

我的 CAS 确实从 LDAP 获取角色,但我不希望我的 Web 应用程序与 LDAP 对话。

是否可以配置spring security + CAS来获取ldap属性?

有人可以帮我在 CAS 认证后获取 LDAP 属性(例如国家/地区)吗?

Get LDAP user attributes from CAS

我已附上我的 CAS deployerConfigContext.xml

            <?xml version="1.0" encoding="UTF-8"?>



            <beans xmlns="http://www.springframework.org/schema/beans"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xmlns:p="http://www.springframework.org/schema/p"
                   xmlns:c="http://www.springframework.org/schema/c"
                   xmlns:tx="http://www.springframework.org/schema/tx"
                   xmlns:util="http://www.springframework.org/schema/util"
                   xmlns:sec="http://www.springframework.org/schema/security"
                   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
                   http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
                   http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">



                 <bean id="authenticationManager" class="xxx.cas.authentication.XXXOTPPolicyBasedAuthenticationManager">

                    <constructor-arg index="0">
                        <list value-type="org.jasig.cas.authentication.AuthenticationHandler" >
                            <ref local="ldapAuthenticationHandler"/>
                            <ref local="radiusAuthenticationHandler"/>
                        </list>
                    </constructor-arg> 


                    <property name="authenticationPolicy">
                        <bean class="xxx.cas.authentication.XXXAllAuthenticationPolicy" />
                    </property>
                </bean>

                <!-- Required for proxy ticket mechanism. -->
                <bean id="proxyAuthenticationHandler"
                      class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
                      p:httpClient-ref="httpClient" p:requireSecure="false" />



                   <!--
                   | Change principalIdAttribute to use another directory attribute,
                   | e.g. userPrincipalName, for the NetID
                   -->
                <bean id="ldapAuthenticationHandler"
                      class="org.jasig.cas.authentication.LdapAuthenticationHandler"
                      p:principalIdAttribute="sAMAccountName"
                      c:authenticator-ref="authenticator">
                    <property name="principalAttributeMap">
                        <map>
                            <!--
                               | This map provides a simple attribute resolution mechanism.
                               | Keys are LDAP attribute names, values are CAS attribute names.
                               | Use this facility instead of a PrincipalResolver if LDAP is
                               | the only attribute source
                               -->
                            <entry key="displayName" value="displayName" />
                            <entry key="facsimileTelephoneNumber" value="facsimileTelephoneNumber" />
                            <entry key="memberOf" value="memberOf" />
                            <entry key="co" value="co" />
                            <entry key="c" value="c" />
                            <entry key="mail" value="mail" />
                            <entry key="description" value="role" />
                        </map>
                    </property>
                </bean>



                <!-- Required for proxy ticket mechanism -->
                <bean id="proxyPrincipalResolver"
                      class="org.jasig.cas.authentication.principal.BasicPrincipalResolver" />


                <!-- Radius authentication -->
                <bean id="radiusClientFactory"
                      class="org.jasig.cas.adaptors.radius.RadiusClientFactory"
                      p:inetAddress="${fourtress.server}"
                      p:sharedSecret="${fourtress.ss}" />

                <bean id="radiusServer"
                      class="org.jasig.cas.adaptors.radius.JRadiusServerImpl"
                      c:protocol="PAP"
                      c:clientFactory-ref="radiusClientFactory" />

                <bean id="radiusAuthenticationHandler"
                      class="xxx.cas.authentication.XXXRadiusAuthenticationHandler">
                  <property name="servers">
                      <list>
                          <ref local="radiusServer" />
                      </list>
                  </property>
                </bean>




                <bean id="attributeRepository"
                  class="org.jasig.cas.persondir.LdapPersonAttributeDao"
                  p:connectionFactory-ref="pooledLdapConnectionFactory"
                  p:baseDN="ou=users,ou=egate,dc=egate-t,dc=local" p:searchControls-ref="searchControls" p:searchFilter="sAMAccountName={0}">

                    <property name="requireAllQueryAttributes" value="true"/>
                    <property name="queryAttributeMapping">
                        <map>
                            <!-- Attribute mapping between principal (key) and LDAP (value) names used to perform the LDAP search -->
                            <entry key="username" value="sAMAccountName" />
                        </map>
                    </property>
                    <property name="resultAttributeMapping">
                        <map>
                            <!-- Mapping between LDAP entry attributes (key) and Principal's (value) -->
                            <entry key="memberOf" value="memberOf" />
                            <entry key="mail" value="mail" />
                            <entry key="cn" value="FullName" />
                            <entry key="sn" value="LastName" />
                            <entry key="displayName" value="displayName" />
                            <entry key="description" value="role" />
                            <entry key="facsimileTelephoneNumber" value="facsimileTelephoneNumber" />
                            <entry key="co" value="country" />
                            <entry key="c" value="countryCode" />

                        </map>
                    </property>
                </bean>

                <bean id="searchControls"
                      class="javax.naming.directory.SearchControls"
                      p:searchScope="2"
                      p:countLimit="0" p:timeLimit="0" />


                <!--
                Sample, in-memory data store for the ServiceRegistry. A real implementation
                would probably want to replace this with the JPA-backed ServiceRegistry DAO
                The name of this bean should remain "serviceRegistryDao".
                +-->
                <bean id="serviceRegistryDao" class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl"
                        p:registeredServices-ref="registeredServicesList" />

                <util:list id="registeredServicesList">

                    <bean class="org.jasig.cas.services.RegexRegisteredService">
                        <property name="id" value="1" />
                        <property name="name" value="cassimple" />
                        <property name="description" value="cassimple application 1" />
                        <property name="serviceId" value="^(http?|https?|imaps?)://localhost:7002/cassimple/.*" />
                        <property name="evaluationOrder" value="10000001" />
                    </bean>

                    <bean class="org.jasig.cas.services.RegexRegisteredService">
                        <property name="id" value="2" />
                        <property name="name" value="casldap" />
                        <property name="description" value="casldap application 2" />
                        <property name="serviceId" value="^(http?|https?|imaps?)://localhost:7002/casldap/.*" />
                        <property name="evaluationOrder" value="10000002" />
                        <property name="allowedAttributes">
                            <list>
                                <value>memberOf</value>
                                <value>LastName</value>
                                <value>FullName</value>
                                <value>displayName</value>
                                <value>role</value>
                            </list>
                        </property>            
                    </bean>

                    <bean class="org.jasig.cas.services.RegexRegisteredService">
                        <property name="id" value="3" />
                        <property name="name" value="cascir" />
                        <property name="description" value="cas cir application 3" />
                        <property name="serviceId" value="^(http?|https?|imaps?)://localhost:7002/cascir/.*" />
                        <property name="evaluationOrder" value="10000003" />
                        <property name="allowedAttributes">
                            <list>
                                <value>role</value>
                                <value>FullName</value>
                                <value>displayName</value>
                                <value>LastName</value>
                                <value>memberOf</value>
                            </list>
                        </property>            
                    </bean>

                    <bean class="org.jasig.cas.services.RegexRegisteredService">
                        <property name="id" value="4" />
                        <property name="name" value="egate" />
                        <property name="description" value="cas egate application 4" />
                        <property name="serviceId" value="^(http?|https?|imaps?)://localhost:7002/egate/.*" />
                        <property name="evaluationOrder" value="10000004" />
                        <property name="allowedAttributes">
                            <list>
                                <value>role</value>
                                <value>FullName</value>
                                <value>displayName</value>
                                <value>LastName</value>
                                <value>memberOf</value>
                            </list>
                        </property>            
                    </bean>

                    <bean class="org.jasig.cas.services.RegexRegisteredService">
                        <property name="id" value="5" />
                        <property name="name" value="cir" />
                        <property name="description" value="cas cir application 5" />
                        <property name="serviceId" value="^(http?|https?|imaps?)://localhost:7002/cir/.*" />
                        <property name="evaluationOrder" value="10000005" />
                        <property name="allowedAttributes">
                            <list>
                                <value>role</value>
                                <value>FullName</value>
                                <value>displayName</value>
                                <value>LastName</value>
                                <value>memberOf</value>
                                <value>country</value>
                                <value>countryCode</value>
                            </list>
                        </property>            
                    </bean>





                </util:list>

                <bean id="auditTrailManager" class="com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager" />

                <bean id="healthCheckMonitor" class="org.jasig.cas.monitor.HealthCheckMonitor" p:monitors-ref="monitorsList" />

                <util:list id="monitorsList">
                  <bean class="org.jasig.cas.monitor.MemoryMonitor" p:freeMemoryWarnThreshold="10" />
                  <!--
                    NOTE
                    The following ticket registries support SessionMonitor:
                      * DefaultTicketRegistry
                      * JpaTicketRegistry
                    Remove this monitor if you use an unsupported registry.
                  -->
                  <bean class="org.jasig.cas.monitor.SessionMonitor"
                      p:ticketRegistry-ref="ticketRegistry"
                      p:serviceTicketCountWarnThreshold="5000"
                      p:sessionCountWarnThreshold="100000" />
                </util:list>


                <bean id="authenticator" class="org.ldaptive.auth.Authenticator"
                      c:resolver-ref="dnResolver"
                      c:handler-ref="authHandler"
                      p:entryResolver-ref="entryResolver" />

                <!-- Active Directory UPN format. -->
                <bean id="dnResolver"
                      class="org.ldaptive.auth.FormatDnResolver"
                      c:format="${ldap.authn.format}" />

                <bean id="authHandler" class="org.ldaptive.auth.PooledBindAuthenticationHandler"
                      p:connectionFactory-ref="pooledLdapConnectionFactory" />

                <bean id="pooledLdapConnectionFactory" 
                      class="org.ldaptive.pool.PooledConnectionFactory"
                      p:connectionPool-ref="connectionPool" />


                <bean id="connectionPool"
                      class="org.ldaptive.pool.BlockingConnectionPool"
                      init-method="initialize"
                      p:poolConfig-ref="ldapPoolConfig"
                      p:blockWaitTime="${ldap.pool.blockWaitTime}"
                      p:validator-ref="searchValidator"
                      p:pruneStrategy-ref="pruneStrategy"
                      p:connectionFactory-ref="connectionFactory" />

                <bean id="ldapPoolConfig" class="org.ldaptive.pool.PoolConfig"
                      p:minPoolSize="${ldap.pool.minSize}"
                      p:maxPoolSize="${ldap.pool.maxSize}"
                      p:validateOnCheckOut="${ldap.pool.validateOnCheckout}"
                      p:validatePeriodically="${ldap.pool.validatePeriodically}"
                      p:validatePeriod="${ldap.pool.validatePeriod}" />

                <bean id="connectionFactory" class="org.ldaptive.DefaultConnectionFactory"
                      p:connectionConfig-ref="connectionConfig" />

                <bean id="connectionConfig" class="org.ldaptive.ConnectionConfig"
                      p:ldapUrl="${ldap.url}"
                      p:connectTimeout="${ldap.connectTimeout}"
                      p:useStartTLS="${ldap.useStartTLS}"
                      p:sslConfig-ref="sslConfig"/>

                <bean id="sslConfig" class="org.ldaptive.ssl.SslConfig">
                    <property name="credentialConfig">
                        <bean class="org.ldaptive.ssl.X509CredentialConfig"
                              p:trustCertificates="classpath:${ldap.trustedCert}" />
                    </property>
                </bean>

                <bean id="pruneStrategy" class="org.ldaptive.pool.IdlePruneStrategy"
                      p:prunePeriod="${ldap.pool.prunePeriod}"
                      p:idleTime="${ldap.pool.idleTime}" />

                <bean id="searchValidator" class="org.ldaptive.pool.SearchValidator" />

                <bean id="entryResolver"
                      class="org.jasig.cas.authentication.support.UpnSearchEntryResolver"
                      p:baseDn="${ldap.baseDn}" />


            </beans>

我的 spring security.xml

        <beans:beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans"
            xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
            http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">

            <debug />


            <global-method-security secured-annotations="enabled" />

            <http auto-config="false" use-expressions="true"
                entry-point-ref="casAuthenticationEntryPoint">

                <custom-filter position="CAS_FILTER" ref="casAuthenticationFilter" />


                <intercept-url pattern="/faces/disclaimer**" access="permitAll" />
                <intercept-url pattern="/faces/searchCreditInstitution**"
                    access="permitAll" />
                <intercept-url pattern="/faces/searchParentInstitution**"
                    access="hasAnyRole('ROLE_CIR_EDITOR','ROLE_CIR_AUTHORISER')" />
                <intercept-url pattern="/faces/createCreditInstitution**"
                    access="hasAuthority('ROLE_CIR_EDITOR')" />
                <intercept-url pattern="/faces/authorisation**"
                    access="hasAuthority('ROLE_CIR_AUTHORISER')" />
                <intercept-url pattern="/faces/rejected**" access="hasAuthority('ROLE_CIR_EDITOR')" />
                <intercept-url pattern="/faces/pendingApproval**"
                    access="hasAuthority('ROLE_CIR_EDITOR')" />
                <intercept-url pattern="/faces/auditLog**"
                    access="hasAuthority('ROLE_CIR_AUTHORISER')" />
                <intercept-url pattern="/faces/enquiry**"
                    access="hasAnyRole('ROLE_CIR_EDITOR','ROLE_CIR_AUTHORISER','ROLE_CIR_XXXOPS')" />
                <intercept-url pattern="/faces/changePassword**"
                    access="hasAnyRole('ROLE_CIR_EDITOR','ROLE_CIR_AUTHORISER','ROLE_CIR_XXXOPS')" />
                <intercept-url pattern="/faces/dashboard**" access="ROLE_CIR_XXXOPS" />
                <intercept-url pattern="/resources**" access="permitAll" />
                <intercept-url pattern="/faces/javax.faces.resource**" access="permitAll" />
                <logout logout-url="/logout" logout-success-url="https://localhost:7002/cas/logout" />

            </http>

            <beans:bean id="serviceProperties"
                class="org.springframework.security.cas.ServiceProperties">
                <beans:property name="service"
                    value="https://localhost:7002/cir/j_spring_cas_security_check" />
                <beans:property name="sendRenew" value="false" />
            </beans:bean>

            <beans:bean id="casAuthenticationEntryPoint"
                class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
                <beans:property name="loginUrl" value="https://localhost:7002/cas/login" />
                <beans:property name="serviceProperties" ref="serviceProperties" />
            </beans:bean>

            <beans:bean id="casAuthenticationFilter"
                class="org.springframework.security.cas.web.CasAuthenticationFilter">
                <beans:property name="authenticationManager" ref="casAuthenticationManager" />
            </beans:bean>

            <authentication-manager alias="casAuthenticationManager">
                <authentication-provider ref="casAuthenticationProvider" />
            </authentication-manager>

            <beans:bean id="casAuthenticationProvider"
                class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
                <beans:property name="serviceProperties" ref="serviceProperties" />
                <beans:property name="ticketValidator" ref="ticketValidator" />
                <beans:property name="authenticationUserDetailsService"
                    ref="authenticationUserDetailsService" />
                <beans:property name="key" value="cir" />
            </beans:bean>

            <beans:bean id="ticketValidator"
                class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
                <beans:constructor-arg index="0"
                    value="https://localhost:7002/cas">
                </beans:constructor-arg>
            </beans:bean>

            <beans:bean id="authenticationUserDetailsService"
                class="XXX.cir.cas.authentication.XXXCasAuthenticationUserDetailsService" />

        </beans:beans>

我可以通过这种方式获取 Ldap 角色、JSF 托管 bean 中的用户名,但不能获取国家/地区

                SecurityContext ctx = SecurityContextHolder.getContext();

                UserDetails userDetails = (UserDetails)ctx.getAuthentication().getPrincipal();      

                System.out.println("Role of the ldaper : " + ctx.getAuthentication().getAuthorities());     

                String userRole = ctx.getAuthentication().getAuthorities(); 

最佳答案

我没有使用过 Spring Security,但一个选项可能是 AttributeRepository,以便直接从 cas 获取属性,而不是从应用程序中检索。您可以将 attributeRepository 添加到deployerContext(beanauthenticationManager,属性credentialsToPrincipalResolvers:

 <bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver" 
                p:attributeRepository-ref="attributeRepository"/>

以及以下 Bean:

<bean id="attributeRepository" parent="baseAttributeRepository">
    <property name="personAttributeDaos">
        <list>
            <ref local="ldapAttributesByUid" />
        </list>
    </property>
</bean>  
<bean id="ldapAttributesByUid" parent="baseLdapAttributeRepository"
      class="org.jasig.services.persondir.support.ldap.LdapPersonAttributeDao">
    <property name="queryAttributeMapping">
        <map>
            <entry key="username" value="uid" /> 
        </map>
    </property>
</bean>    
<bean id="baseLdapAttributeRepository" abstract="true"
      p:contextSource-ref="contextSource"
      p:baseDN="o=xxxxxx,dc=xxxxx"
      p:requireAllQueryAttributes="true">
    <property name="resultAttributeMapping">
        <map>
            <entry key="accountState" value="accountState" /> 
            <entry key="authId">
                <list>
                    <value>authId</value>
                    <value>Formatted Name</value>
                </list>
            </entry>
            <entry key="groupMembership" value="groupMembership" />
            <entry key="uid" value="uid" />
            <entry key="sn" value="sn" />
            <entry key="sn2" value="sn2" />
            <entry key="givenName" value="givenName" />
        </map>
    </property>
</bean>  

据我所知,请记住必须使用 SAML 而不是 CAS 协议(protocol)。更多信息请访问https://wiki.jasig.org/display/CASUM/Attributes

希望这有帮助

关于java - CAS 身份验证后获取 JSF Managed Bean 中的 LDAP 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26928957/

相关文章:

java - "? :"指令错误。不是一个声明

java - 关于基于 Spring security URL 的安全性的说明

java - Spring-websockets : Spring security authorization not working inside websockets

session - 当浏览器关闭时 Spring Security 不会终止 session

java - 找到最长的公共(public)前缀?

java - 使用 Java DateTimeFormatter 类使用 am/pm 解析一天中的时间

java - 内存不足错误: unable to create new native thread

jsf - 将 java.util.Date 拆分为两个 h :inputText fields representing hour and minute with f:convertDateTime

java - Facelet VDL 官方规范在哪里?

java - 如何使用 AJAX 使两个 JSF selectOneMenu 相互依赖?