2011-09-05 9 views
23

Soy muy nuevo en Spring and Spring Security y espero que alguien me pueda ayudar a resolver el siguiente problema.Spring Security con Openid y la integración de bases de datos

Lo que quiero lograr es extraer el nombre de usuario y la dirección de correo electrónico del usuario después de que el proveedor de OpenID (gmail) haya autenticado con éxito, luego verifique con la base de datos para cargar el modelo de usuario de este usuario.

En mi primavera-security.xml, tengo

 
<?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:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:security="http://www.springframework.org/schema/security" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
          http://www.springframework.org/schema/context 
          http://www.springframework.org/schema/context/spring-context-3.0.xsd 
          http://www.springframework.org/schema/security 
          http://www.springframework.org/schema/security/spring-security-3.0.xsd"> 

    <security:authentication-manager alias="openIDAuthenticationManager" /> 

    <bean id="authenticationSuccessHandler" class="org.school.openid.service.YouEatAuthenticationSuccessHandler"> 
     <property name="defaultTargetUrl" value="/krams/main/common" /> 
     <property name="attributes2UserDetails" ref="openIDAttributes2UserDetails" /> 
    </bean> 

    <security:http > 
     <security:anonymous enabled="false" /> 
     <security:logout /> 
     <security:openid-login user-service-ref="userDetailsServiceOpenIDImpl" authentication-success-handler-ref="authenticationSuccessHandler" 
      login-page="/krams/auth/login" authentication-failure-url="/krams/auth/login?error=true"> 
      <security:attribute-exchange> 
       <security:openid-attribute name="email" type="http://schema.openid.net/contact/email" required="true" /> 
       <security:openid-attribute name="firstName" type="http://axschema.org/namePerson/first" required="true" /> 
       <security:openid-attribute name="lastName" type="http://axschema.org/namePerson/last" required="true" /> 
      </security:attribute-exchange> 
     </security:openid-login> 
    </security:http> 

    <bean id="openIDAttributes2UserDetails" class="org.school.openid.service.OpenIDAttributes2UserDetailsImpl" /> 

    <bean id="userDetailsServiceOpenIDImpl" class="org.school.openid.service.UserDetailsServiceOpenIDImpl" /> 

</beans> 

mi problema está en UserDetailsServiceOpenIDImpl.java es

 
public class UserDetailsServiceOpenIDImpl implements UserDetailsService { 

    public UserDetails loadUserByUsername(String username) 
      throws UsernameNotFoundException, DataAccessException { 
     System.out.println(username); 
     //extract username and email address, HOW? 
    } 
} 

Las impresiones de los estados de impresión fuera algo así como

 
https://www.google.com/accounts/o8/id?id=AItOawlq2C3EdFAuqp-ski_xkgB8jsEKbe-mZE 

Mis preguntas son

(1) ¿Cómo podría extraer el nombre de usuario y la dirección de correo electrónico de la URL devuelta (además, ni siquiera estoy seguro de si el nombre de usuario y la dirección de correo electrónico fueron correctos)?

(2) Al ejecutar la depuración en Eclipse, el YouEatAuthenticationSuccessHandler no parece invocado cuando se devuelve la url (https://www.google.com/accounts/o8/id?id=AItOawlq2C3EdFAuqp-ski_xkgB8jsEKbe-mZE).

Gracias.

Editar: gracias por el enlace http://static.springsource.org/spring-security/site/docs/3.0.x/reference/ns-config.html#ns-openid.

Se dice que "Los valores de los atributos se devuelven como parte del proceso de autenticación y se puede acceder posteriormente mediante el código siguiente: ..."

He añadido

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

en el método loadUserByUsername . Pero el objeto "token" es nulo.

Editar 2 Siguiendo página https://fisheye.springsource.org/browse/spring-security/samples/openid/src/main/webapp/WEB-INF/applicationContext-security.xml?hb=true, soy capaz de extra, el nombre y dirección de correo electrónico para el usuario. Mi primavera-security.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:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:security="http://www.springframework.org/schema/security" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
          http://www.springframework.org/schema/context 
          http://www.springframework.org/schema/context/spring-context-3.0.xsd 
          http://www.springframework.org/schema/security 
          http://www.springframework.org/schema/security/spring-security-3.1.xsd"> 
    <security:authentication-manager alias="openIDAuthenticationManager" /> 
    <security:http pattern="/krams/auth/login" security="none"/> 
    <security:http auto-config="true" access-denied-page="/krams/auth/denied"> 
     <security:intercept-url pattern="/krams/main/*" access="ROLE_USER" /> 
     <security:anonymous enabled="false" /> 
     <security:logout 
      invalidate-session="true" 
      logout-success-url="/krams/auth/login" 
      logout-url="/krams/auth/logout"/> 
     <security:openid-login 
      user-service-ref="registeringUserService" 
      login-page="/krams/auth/login" 
      authentication-failure-url="/krams/auth/login?error=true" 
      default-target-url="/krams/main/common"> 
      <security:attribute-exchange identifier-match="https://www.google.com/.*"> 
       <security:openid-attribute name="email" type="http://schema.openid.net/contact/email" required="true" /> 
       <security:openid-attribute name="firstName" type="http://axschema.org/namePerson/first" required="true" /> 
       <security:openid-attribute name="lastName" type="http://axschema.org/namePerson/last" required="true" /> 
      </security:attribute-exchange> 
      <security:attribute-exchange identifier-match=".*yahoo.com.*"> 
       <security:openid-attribute name="email" type="http://axschema.org/contact/email" required="true"/> 
       <security:openid-attribute name="fullname" type="http://axschema.org/namePerson" required="true" /> 
      </security:attribute-exchange> 
     </security:openid-login> 
     <!-- if remember is needed 
     <security:remember-me token-repository-ref="tokenRepo"/> 
     -->  
    </security:http> 
    <bean id="tokenRepo" class="org.springframework.security.web.authentication.rememberme.InMemoryTokenRepositoryImpl" /> 
<!-- 
    A custom UserDetailsService which will allow any user to authenticate and "register" their IDs in an internal map 
    for use if they return to the site. This is the most common usage pattern for sites which use OpenID. 
--> 
    <bean id="registeringUserService" class="org.school.openid.service.CustomUserDetailsService" /> 
</beans> 

Mi CustomUserDetailsService.java

 
public class CustomUserDetailsService implements AuthenticationUserDetailsService { 

    /* 
    private final Map registeredUsers = new HashMap(); 
    */ 
     private static final List DEFAULT_AUTHORITIES = AuthorityUtils.createAuthorityList("ROLE_USER"); 
    protected static Logger logger = Logger.getLogger("service");  
    /** 
    * Implementation of {@code AuthenticationUserDetailsService} which allows full access to the submitted 
    * {@code Authentication} object. Used by the OpenIDAuthenticationProvider. 
    */ 
    public UserDetails loadUserDetails(OpenIDAuthenticationToken token) { 
     String id = token.getIdentityUrl(); 
     String email = null; 
     String firstName = null; 
     String lastName = null; 
     String fullName = null; 
     List attributes = token.getAttributes(); 
     for (OpenIDAttribute attribute : attributes) { 
      if (attribute.getName().equals("email")) { 
       email = attribute.getValues().get(0); 
      } 
      if (attribute.getName().equals("firstName")) { 
       firstName = attribute.getValues().get(0); 
      } 
      if (attribute.getName().equals("lastName")) { 
       lastName = attribute.getValues().get(0); 
      } 
      if (attribute.getName().equals("fullname")) { 
       fullName = attribute.getValues().get(0); 
      } 
     } 
     if (fullName == null) { 
      StringBuilder fullNameBldr = new StringBuilder(); 
      if (firstName != null) { 
       fullNameBldr.append(firstName); 
      } 
      if (lastName != null) { 
       fullNameBldr.append(" ").append(lastName); 
      } 
      fullName = fullNameBldr.toString(); 
     } 
     CustomUserDetails user = new CustomUserDetails(id,fullName,email, DEFAULT_AUTHORITIES);   
     logger.debug("Set username " + fullName + " email " + email); 
     return user; 
    } 
} 

Mi CustomUserDetails.java

 
public class CustomUserDetails extends User { 
    private static final long serialVersionUID = 1L; 
    private String email; 
    private String name; 
    public CustomUserDetails(String id,String name, String email,Collection authorities) { 
     super(name, "unused", true,true,true,true,authorities); 
     this.email = email; 
     this.name = name; 
    } 
    public String getEmail() { 
     return email; 
    } 

    public void setEmail(String email) { 
     this.email = email; 
    } 
    public void setName(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return name; 
    } 
} 

Y

 
... 
<repository> 
    <id>org.springframework.maven.milestone</id> 
    <name>Spring Maven Milestone Repository</name> 
    <url>http://maven.springframework.org/milestone</url> 
</repository> 
... 
<dependency> 
    <groupId>org.springframework.security</groupId> 
    <artifactId>spring-security-core</artifactId> 
    <version>3.1.0.RC1</version> 
</dependency> 
<dependency> 
    <groupId>org.springframework.security</groupId> 
    <artifactId>spring-security-web</artifactId> 
    <version>3.1.0.RC1</version> 
    <type>jar</type> 
     <scope>compile</scope> 
</dependency> 
<dependency> 
     <groupId>org.springframework.security</groupId> 
     <artifactId>spring-security-config</artifactId> 
     <version>3.1.0.RC1</version> 
    </dependency> 
     <dependency> 
     <groupId>org.springframework.security</groupId> 
     <artifactId>spring-security-openid</artifactId> 
     <version>3.1.0.RC1</version> 
    </dependency> 
    <dependency> 
    <groupId>org.springframework</groupId> 
<artifactId>spring-webmvc</artifactId> 
<version>3.0.5.RELEASE</version> 
</dependency> 
    <dependency> 
     <groupId>org.springframework.security</groupId> 
     <artifactId>spring-security-openid</artifactId> 
     <version>3.1.0.RC1</version> 
     <type>pom</type> 
     <scope>compile</scope> 
    </dependency> 

La esperanza puede ahorrar algo hora.

+5

Si no le importa separar su pregunta de su respuesta y publicar una respuesta aquí, estaría bien. Parece que tienes una solución para tu problema, pero no es del todo visible. – Makoto

+2

Es posible que desee ver Spring Social para algo como esto. Lo uso para uno de mis proyectos y es mucho más simple de integrar que todo esto. Su documentación es lo suficientemente buena y tienen algunos ejemplos de uso en github. –

+0

Estoy de acuerdo, mira en primavera social. –

Respuesta

1

Como veo que el texto de la pregunta en sí contiene la respuesta. Solo lo estoy sacando y publicando como respuesta en aras de la claridad para otros desarrolladores con el mismo problema. Me tomó un tiempo darme cuenta de que la pregunta tiene la respuesta.

Para acceder al correo electrónico de usuario &, debe agregar la configuración siguiente en el archivo de seguridad xml.

<security:attribute-exchange identifier-match="https://www.google.com/.*"> 
    <security:openid-attribute name="email" type="http://schema.openid.net/contact/email" required="true" /> 
    <security:openid-attribute name="firstName" type="http://axschema.org/namePerson/first" required="true" /> 
    <security:openid-attribute name="lastName" type="http://axschema.org/namePerson/last" required="true" /> 
</security:attribute-exchange> 
<security:attribute-exchange identifier-match=".*yahoo.com.*"> 
    <security:openid-attribute name="email" type="http://axschema.org/contact/email" required="true"/> 
    <security:openid-attribute name="fullname" type="http://axschema.org/namePerson" required="true" /> 
</security:attribute-exchange> 

A partir de entonces, será accesible en la clase AuthenticationUserDetailsService, como se muestra a continuación.

public UserDetails loadUserDetails(OpenIDAuthenticationToken token) { 
    String id = token.getIdentityUrl(); 
     : 
     : 
    List attributes = token.getAttributes(); 
    for (OpenIDAttribute attribute : attributes) { 
     if (attribute.getName().equals("email")) { 
      email = attribute.getValues().get(0); 
     } 
     if (attribute.getName().equals("firstName")) { 
      firstName = attribute.getValues().get(0); 
     } 
     if (attribute.getName().equals("lastName")) { 
      lastName = attribute.getValues().get(0); 
     } 
     if (attribute.getName().equals("fullname")) { 
      fullName = attribute.getValues().get(0); 
     } 
    } 
     : 
     : 
    // form and return user object 
} 

Teniendo en cuenta que usamos más de configuración/frijoles basadas en Java ahora, la traducción de estos configuración XML para la configuración basada en Java no debería ser un problema.

Espero que ayude.

Cuestiones relacionadas