Аутентификация OpenId и автоматическая регистрация в Spring Security 3.0.2 - PullRequest
8 голосов
/ 27 апреля 2010

Я реализую приложение, используя Spring Security 3.0.2 с OpenId для входа и регистрации.Я могу успешно войти в систему, но если пользователь не зарегистрирован, я хочу сделать:

1) Получить некоторые атрибуты OpenId, такие как электронная почта и имя.2) Покажите пользователю регистрационную форму только с этими двумя полями и заполненным URI OpenId.

Я много искал, но не нашел "элегантного" способа сделать это.Интересно, могут ли некоторые из вас предложить решение для реализации этой стратегии в моем приложении.

Заранее спасибо.

Ответы [ 2 ]

5 голосов
/ 01 мая 2010

Невозможно отобразить адрес электронной почты и имя до того, как пользователь сам зарегистрируется / войдет в систему, поскольку он должен сначала разрешить приложению доступ к своему профилю. Вы можете показать ему эту страницу с его openid, почтой и т. Д. после того, как он вошел в систему.

Определите, какие атрибуты вы хотите использовать:

<openid-login login-page="/openidlogin.jsp" authentication-failure-url="/openidlogin.jsp?login_error=true">
  <attribute-exchange>
    <openid-attribute name="email" type="http://schema.openid.net/contact/email" required="true" count="2"/>
    <openid-attribute name="name" type="http://schema.openid.net/namePerson/friendly" />
  </attribute-exchange>
</openid-login>

И затем получить доступ к атрибутам после входа пользователя в систему:

OpenIDAuthenticationToken token = (OpenIDAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();
List<OpenIDAttribute> attributes = token.getAttributes();

Посмотрите на пример из репозитория и документацию поддержки OpenId .

0 голосов
/ 20 ноября 2011

Это не реализовано в Spring security <3.1 </p>

Однако вы можете использовать обходной путь с apectJ. Определите следующий аспект:

package org.acoveo.spring.utils;
@Aspect
public class OpenIDSpringAuthenticationHackAspect {
    static ThreadLocal<Authentication> authHolder = new ThreadLocal<Authentication>();
    @Around(value="execution(* org.springframework.security.openid.OpenIDAuthenticationProvider.authenticate(..))")
    public Object around(ProceedingJoinPoint jp) throws Throwable {
        try {
            Authentication auth = (Authentication) jp.getArgs()[0];
            authHolder.set(auth);
            Object returnVal = jp.proceed();
            authHolder.set(null);
            return returnVal;
        }catch(Throwable e) {
            System.out.println("Exception while running OpenIDSpringAuthenticationHackAspect");
            e.printStackTrace();
            return null;
        }
    }
    public static Authentication getTransientAuthentication() {
        return authHolder.get();
    }
}

и зарегистрируйте его в своем aop.xml:

<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">  
<aspectj>
    <weaver options="-showWeaveInfo -verbose" />
    <weaver>
        <include within="org.springframework.security.openid..*" />
        <!-- This is required to make the spring instrument javaagent work with hibernate CGLIB
         -->
        <exclude within="*..*CGLIB*" />
    </weaver>
    <aspects>
        <aspect name="org.acoveo.spring.utils.OpenIDSpringAuthenticationHackAspect" />
    </aspects>
</aspectj>

Затем в вашем UserDetailsService вы можете получить доступ к атрибутам OpenID следующим образом:

public UserDetails loadUserByUsername(String username, boolean includeTemporary) throws UsernameNotFoundException, DataAccessException {
    Authentication auth = OpenIDSpringAuthenticationHackAspect.getTransientAuthentication();
    if(auth != null && auth instanceof OpenIDAuthenticationToken) {
        // First try to find the user by their openid email address
        OpenIDAuthenticationToken openIdToken = (OpenIDAuthenticationToken)auth;
        String email = null;
        for(OpenIDAttribute attr : openIdToken.getAttributes()) {
            if("email".equals(attr.getName()) && attr.getValues() != null && !attr.getValues().isEmpty()) {
                email = attr.getValues().get(0);
                break;
            }
        }
        // TODO retrieve and return user
...