Получение большего количества атрибутов от CAS, чем просто идентификатор пользователя - PullRequest
14 голосов
/ 03 февраля 2011

Я использую CAS с обработчиком аутентификации JDBC, и мне было интересно, можно ли получить другие атрибуты основного объекта (например, имя, фамилия), а не только имя пользователя из CAS после успешной аутентификации?

Ответы [ 5 ]

11 голосов
/ 15 мая 2012

В casServiceValidationSuccess.jsp я добавляю как показано ниже:

<cas:attributes>

    <c:forEach var="attr" items="${assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes}">
         **<cas:${fn:escapeXml(attr.key)}>${fn:escapeXml(attr.value)}</cas:${fn:escapeXml(attr.key)}>**
    </c:forEach>

</cas:attributes>

В deployerConfigContent.xml я добавляю как ниже:

<bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver" >

    **<property name="attributeRepository">
     <ref bean="attributeRepository" />
    </property>**

</bean>

<bean id="attributeRepository" class="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao">

    <constructor-arg index="0" ref="dataSource"/>
    <constructor-arg index="1" value="select * from bbs_members where {0}" />
    <property name="queryAttributeMapping">
       <map>
          <entry key="username" value="username" />
       </map>
    </property>

    <property name="resultAttributeMapping">
        <map>
            <entry key="uid" value="uid"/>
            <entry key="email" value="email"/>
            <entry key="password" value="password"/>
        </map>
    </property>
</bean>

Этоработает.Я столкнулся с этой проблемой во время отладки. Пожалуйста, закройте браузер, если вы измените этот файл JSP или XML, иначе изменения не будут работать.Будьте осторожны.

3 голосов
/ 22 апреля 2016

Чтобы получить любые пользовательские атрибуты из БД, я сделал следующее: используйте PersonDirectoryPrincipalResolver

в deployerConfigContext.xml:

<bean id="primaryPrincipalResolver"
      class="org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver" >
    <property name="attributeRepository" ref="singleRowJdbcPersonMultiplyAttributeDao" />
</bean>

вместо использования стандартного Класс SingleRowJdbcPersonAttributeDao создает собственную реализацию, которая возвращает не только одну строку из результата запроса, но и агрегированные данные из всех возвращаемых строк:

копирует весь код из SingleRowJdbcPersonAttributeDao и изменяет только один метод parseAttributeMapFromResults.у вас будет что-то вроде этого:

public class SingleRowJdbcPersonMultiplyAttributeDao extends AbstractJdbcPersonAttributeDao<Map<String, Object>> {
    ...

    @Override
    protected List<IPersonAttributes> parseAttributeMapFromResults(final List<Map<String, Object>> queryResults, final String queryUserName) {
        final List<IPersonAttributes> peopleAttributes = new ArrayList<IPersonAttributes>(queryResults.size());
        Map<String, List<Object>> attributes = new HashMap<String, List<Object>>();

        for (final Map<String, Object> queryResult : queryResults) {

            for (final Map.Entry<String, Object> seedEntry : queryResult.entrySet()) {
                final String seedName = seedEntry.getKey();
                final Object seedValue = seedEntry.getValue();

                if (attributes.get(seedName) != null && !attributes.get(seedName).get(0).equals(seedValue)) {
                    attributes.get(seedName).add(seedValue);
                } else {
                    List<Object> list = new ArrayList<Object>();
                    list.add(seedValue);
                    attributes.put(seedName, list);
                }

            }
        }

        final IPersonAttributes person;
        final String userNameAttribute = this.getConfiguredUserNameAttribute();
        if (this.isUserNameAttributeConfigured() && attributes.containsKey(userNameAttribute)) {
            // Option #1:  An attribute is named explicitly in the config,
            // and that attribute is present in the results from LDAP;  use it
            person = new CaseInsensitiveAttributeNamedPersonImpl(userNameAttribute, attributes);
        } else if (queryUserName != null) {
            // Option #2:  Use the userName attribute provided in the query
            // parameters.  (NB:  I'm not entirely sure this choice is
            // preferable to Option #3.  Keeping it because it most closely
            // matches the legacy behavior there the new option -- Option #1
            // -- doesn't apply.  ~drewwills)
            person = new CaseInsensitiveNamedPersonImpl(queryUserName, attributes);
        } else {
            // Option #3:  Create the IPersonAttributes doing a best-guess
            // at a userName attribute
            person = new CaseInsensitiveAttributeNamedPersonImpl(userNameAttribute, attributes);
        }

        peopleAttributes.add(person);
        return peopleAttributes;
    }

    ...
}

и в deployerConfigContext.xml:

<bean id="singleRowJdbcPersonMultiplyAttributeDao"
          class="com.scentbird.SingleRowJdbcPersonMultiplyAttributeDao">
        <constructor-arg index="0" ref="dataSource" />
        <constructor-arg index="1" value="SELECT attributes_table1.*, attributes_table2.attr1, attributes_table2.roles AS roles FROM user_table ut LEFT JOIN roles_table rt ON <condition> LEFT JOIN another_table at ON <condition> WHERE {0}" />
    <property name="queryAttributeMapping">
        <map>
            <entry key="username" value="username" />
        </map>
    </property>
</bean>

Также в моем случае я использовал протокол SAML.

В результате выполучит на клиенте все атрибуты, которые возвращает ваш выбор.Например, если у пользователя много ролей, которые вы могли бы выполнять на клиенте:

Пользователь: имя пользователя, имя, фамилия, адрес электронной почты, ..., [ROLE_1, ROLE_2, ROLE_3]

Мой случайработает с Spring Security и Grails.

Я не уверен, что это 100% -ное решение по фен-шуй :), поскольку оно быстро готовится, но в нашем случае работает.

Надеюсь, это поможет.

2 голосов
/ 23 мая 2011

Я провел последние три дня, пытаясь правильно настроить CAS. Одна из проблем, с которыми я столкнулся, заключалась в том, что я должен был явно указать CAS для публикации свойств. Я сделал это:

  1. открытие https://localhost/cas/services
  2. переход на вкладку «Управление услугами»
  3. нажмите «изменить» для каждой услуги
  4. выделите свойства, которые вы хотите опубликовать
  5. нажмите кнопку сохранения

FWIW, другая проблема заключается в том, что casServiceValidationSuccess.jsp содержит какой-либо код для передачи свойств обратно в ответе. Я искал решение этой проблемы, когда нашел ваш вопрос. Я заметил, что вы переписали свою реализацию.

1 голос
/ 11 декабря 2015

В дополнение к ответу, предоставленному @xiongjiabin, если вы используете CAS v4 +, вы, вероятно, захотите использовать assertion.primaryAuthentication вместо assertion.chainedAuthentications в casServiceValidationSuccess.jsp:

<cas:attributes>
    <c:forEach var="attr" items="${assertion.primaryAuthentication.principal.attributes}">
        <cas:${fn:escapeXml(attr.key)}>${fn:escapeXml(attr.value)}</cas:${fn:escapeXml(attr.key)}>**
    </c:forEach>
</cas:attributes>

Если вы используете assertion.chainedAuthentications с CAS v4 +, тогда serviceRegistryDao список allowedAttributes будет проигнорирован и все атрибуты будут возвращены.

1 голос
/ 23 января 2013

Окончательное и полное решение заключается в следующем (для этой недокументированной функции):

  1. Сторона сервера:

    а. Добавьте attributeRepository к вашему CredentialsToPrincipalResolver.

    б. Реализуйте your.package.YourPersonAttributeDao как IPersonAttributeDao.

    с. Объявите атрибуты, которые будут переданы в утверждение клиенту.

    д. Измените casServiceValidationSuccess.jsp для отображения атрибутов (от xx до xiongjiabin).

  2. Клиентская сторона. Вы получаете все атрибуты, делая это:

    Из-за проблемы с форматированием я не могу опубликовать код окончательного решения .... Дайте мне знать, если вы заинтересованы, я вышлю вам письмо со всем кодом.

...