2011-09-05 147 views
23

我對Spring和Spring Security非常陌生,希望有人能幫助我解決以下問題。Spring Security與OpenID和數據庫集成

我想要實現的是在用戶通過OpenID提供商(gmail)成功驗證後提取用戶的用戶名和電子郵件地址,然後檢查數據庫以便爲該用戶加載usermodel。

在我的彈簧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.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> 

我的問題是在UserDetailsS​​erviceOpenIDImpl.java是

 
public class UserDetailsServiceOpenIDImpl implements UserDetailsService { 

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

print語句打印出類似

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

我的問題是

(1)如何從返回的URL中提取用戶名和電子郵件地址(另外,我甚至不確定用戶名和電子郵件地址是否正確返回)? (2)通過在Eclipse上運行調試,當url(https://www.google.com/accounts/o8/id?id=AItOawlq2C3EdFAuqp-ski_xkgB8jsEKbe-mZE)返回時,YouEatAuthenticationSuccessHandler似乎不會被調用。

謝謝。

編輯: 感謝您的鏈接http://static.springsource.org/spring-security/site/docs/3.0.x/reference/ns-config.html#ns-openid

它說,「屬性值返回作爲認證過程的一部分,以後可以使用下面的代碼進行訪問:......」

我已經加入

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

到loadUserByUsername方法。但是「令牌」對象爲空。

編輯2 通過以下https://fisheye.springsource.org/browse/spring-security/samples/openid/src/main/webapp/WEB-INF/applicationContext-security.xml?hb=true頁,我能夠額外的姓名和電子郵件地址的用戶。 我的彈簧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> 

我CustomUserDetailsS​​ervice.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; 
    } 
} 

我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; 
    } 
} 

而且

 
... 
<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> 

希望可以爲您節省一些 時間。

+5

如果你不介意從你的答案中解決你的問題,並在這裏發佈答案,那會很好。似乎你已經解決了你的問題,但它不是完全可見的。 – Makoto

+2

你可能想看看Spring Social這樣的東西。我將它用於我的一個項目,整合比所有這些要簡單得多。他們的文檔足夠好,他們在github中有一些使用示例。 –

+0

我同意,看看春天的社交。 –

回答

1

正如我看到問題文本本身包含答案。爲了清楚起見,我將其作爲答案發布給其他具有相同問題的開發人員。 我花了一段時間才弄清楚這個問題有答案!

要訪問用戶電子郵件&名稱,您需要在security 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> 

此後,將在AuthenticationUserDetailsService類訪問,如下圖所示。

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 
} 

考慮到我們使用更多的基於Java的配置/豆現在,把這些XML配置基於Java的配置應該不會有問題。

希望它有幫助。