java - 使用 Google 以及 Spring Security 和 Spring Social 登录

标签 java spring spring-security spring-social

我用于此目的的各种 Java 类是

public class GoogleConnectInterceptor extends SpringSocialSecurityConnectInterceptor<Google>{

}

该类提供连接器接口(interface):

public class GoogleProviderConfig extends AbstractProviderConfig<Google>{

    @Autowired
    private ConnectInterceptor<Google> googleConnectInterceptor;

    @Override
    protected ConnectInterceptor<Google> getConnectInterceptor() {
        return googleConnectInterceptor;
    }

}

这是我的 Controller 类方法

@RequestMapping("/protected/google")
    public String helloGoogleProtectedWorld(Map model) {
        model.put("userName", getUserName());

        // Display on the jsp which security level the page is intended for
        model.put("securityLevel", "LinkedIn Protected");

        return "helloWorld";
    }

在下面的类(class)中,我将给出 facebook twitter 和 linkedin 之间连接所需的所有配置。在这个应用程序中,我可以使用 facebook、twitter 和 linkedin 登录,但在使用 google 时失败

@Configuration
@EnableTransactionManagement
@EnableSocial
@PropertySource("classpath:/environment.properties")
public class SocialConfig implements SocialConfigurer {


    // Handle to users connection repository - allows us to set connection sign up in post construct
    private JdbcUsersConnectionRepository usersConnectionRepository;

    @Autowired(required=false)
    private SpringSocialSecurityConnectionSignUp springSocialSecurityConnnectionSignUp;



    @Bean
    public DataSource dataSource() {
        EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
        return builder.setType(EmbeddedDatabaseType.H2).build();
    }


    @Bean 
    public DataSourceTransactionManager transactionManager(DataSource dataSource)
    {
        return new DataSourceTransactionManager(dataSource);
    }

    @Override
    public void addConnectionFactories(
            ConnectionFactoryConfigurer cfConfig,
            Environment env) {
         cfConfig.addConnectionFactory(new TwitterConnectionFactory(
                    env.getProperty("twitter.consumerKey"),
                    env.getProperty("twitter.consumerSecret")
            ));
            cfConfig.addConnectionFactory(new FacebookConnectionFactory(
                    env.getProperty("facebook.clientId"),
                    env.getProperty("facebook.clientSecret")
            ));
            cfConfig.addConnectionFactory(new LinkedInConnectionFactory(
                    env.getProperty("linkedin.consumerKey"),
                    env.getProperty("linkedin.consumerSecret")
            ));
            cfConfig.addConnectionFactory(new GoogleConnectionFactory(
                    env.getProperty("google.clientId"),
                    env.getProperty("google.clientSecret")));
            cfConfig.addConnectionFactory(new SpringSocialSecurityConnectionFactory());
    }

    /**
     * This is only needed because the official spring-social-security from SpringSocial is on the classpath
     * @return
     */
    @Override
    public UserIdSource getUserIdSource() {
         return new AuthenticationNameUserIdSource();
    }


    @Override
    public UsersConnectionRepository getUsersConnectionRepository(
            ConnectionFactoryLocator connectionFactoryLocator) {
        usersConnectionRepository  = new JdbcUsersConnectionRepository(
                dataSource(),
                connectionFactoryLocator,
               Encryptors.noOpText());
        return usersConnectionRepository;

    }



    @PostConstruct
    // Registers a mechanism for implicit sign up if user id available from provider
    // Remove if explicit user name selection is required
    public void registerConnectionSignUp()
    {
        usersConnectionRepository.setConnectionSignUp(springSocialSecurityConnnectionSignUp);
    }


}

下面给出的文件是我的 spring 配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:security="http://www.springframework.org/schema/security"


    xsi:schemaLocation="  http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.0.xsd
         http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.0.xsd              
                http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
                http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <bean
        class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'>
        <property name='location'>
            <value>classpath:environment.properties</value>
        </property>
    </bean>

    <!-- Scan classpath for components, including our Social Security Configuration 
        class -->

    <context:component-scan base-package="org.socialsignin.springsocial.security.config.social" >
    </context:component-scan>

    <context:component-scan base-package="org.socialsignin.springsocial.security" >
    </context:component-scan>


    <context:component-scan base-package="org.socialsignin.provider" />


    <!-- End Spring Social Security -->

    <!-- Start Spring Security -->

    <security:global-method-security
        proxy-target-class="false" >
    </security:global-method-security>


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


    <bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased"
        xmlns="http://www.springframework.org/schema/beans">
        <constructor-arg>
            <list>
                <bean class="org.springframework.security.access.vote.RoleVoter" />
                <bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
            </list>
        </constructor-arg>
    </bean>

    <security:http use-expressions="true"
        entry-point-ref="springSocialSecurityEntryPoint" xmlns="http://www.springframework.org/schema/security">

        <intercept-url pattern="/protected/twitter" access="hasRole('ROLE_USER_TWITTER')" />
        <intercept-url pattern="/protected/facebook" access="hasRole('ROLE_USER_FACEBOOK')" />
        <intercept-url pattern="/protected/linkedin" access="hasRole('ROLE_USER_LINKEDIN')"/>
        <intercept-url pattern="/protected/google" access="hasRole('ROLE_USER_GOOGLE')"/>
        <intercept-url pattern="/protected/facebookTwitter" access="hasRole('ROLE_USER_FACEBOOK') and hasRole('ROLE_USER_TWITTER')" />
        <intercept-url pattern="/protected/**" access="hasRole('ROLE_USER')" />

        <intercept-url pattern="/oauthconnect.jsp" access="hasRole('ROLE_USER')" />

        <access-denied-handler ref="springSocialSecurityAccessDeniedHandler"/>


        <security:logout logout-url="/logout" />

        <anonymous />
        <security:custom-filter position="FORM_LOGIN_FILTER"
            ref="springSocialSecurityAuthenticationFilter" />

        <remember-me services-ref="springSocialSecurityRememberMeServices"
            key="springSocialSecurity" />

    </security:http>


    <bean id="springSocialSecurityEntryPoint"
        class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
        <property name="loginFormUrl" value="/oauthlogin.jsp"/>
    </bean>


    <bean id="springSocialSecurityRememberMeServices"
        class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
        <property name="userDetailsService" ref="springSocialSecurityUserDetailsService" />
        <property name="tokenRepository" ref="tokenRepository" />
        <property name="key" value="springSocialSecurity" />
        <property name="alwaysRemember" value="true" />
        <property name="tokenValiditySeconds" value="3600" />
    </bean>


    <bean id="tokenRepository"
        class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
        <property name="createTableOnStartup" value="true" />
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- End Spring Security -->


    <!-- Start Spring Social -->

    <!-- Transaction manager for a single JDBC DataSource -->

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource"><ref bean="dataSource"/></property>
    </bean>


    <bean class="org.springframework.social.connect.web.ProviderSignInController">
        <constructor-arg value="${application.secureUrl}" />
        <property name="signUpUrl" value="/signup" />
        <property name="postSignInUrl" value="/authenticate" />

        <!-- relies on by-type autowiring for the other constructor-args -->
    </bean>

    <bean class="org.springframework.social.connect.web.ConnectController">
        <!-- relies on by-type autowiring for the constructor-args -->
        <property name="interceptors" ref="connectInterceptorList">
        </property>
    </bean>

    <!--  
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName">
            <value>org.hsqldb.jdbcDriver</value>
        </property>
        <property name="url">
            <value>jdbc:hsqldb:mem:socialsignin</value>
        </property>
        <property name="username">
            <value>sa</value>
        </property>
        <property name="password">
            <value></value>
        </property>
        <property name="defaultAutoCommit">
            <value>true</value>
        </property>
    </bean>
    -->
    <bean id="textEncryptor" class="org.springframework.security.crypto.encrypt.Encryptors"
        factory-method="noOpText" />

    <!-- End Spring Social -->

</beans>

这是我的 JSP 页面,我从这里重定向到 Facebook、LinkedIn 和 Twitter

<html>
 <head>
 </head>
 <body>


<%@ taglib prefix="authz" uri="http://www.springframework.org/security/tags" %>

 <authz:authorize access="!hasRole('ROLE_USER')">


<p>Please log in with a third party provider</p>


  <form class="login"action="http://localhost:8080/spring-social-security-demo-webapp/signin/twitter" method="POST">
    <p><input type="submit" value="Login with Twitter" /></p>
</form> 

  <form class="login"action="http://localhost:8080/spring-social-security-demo-webapp/signin/facebook" method="POST">
    <p><input type="submit" value="Login with Facebook" /></p>
</form> 

<form class="login"action="http://localhost:8080/spring-social-security-demo-webapp/signin/linkedin" method="POST">
    <p><input type="submit" value="Login with LinkedIn" /></p>
</form> 

<form class="login"action="http://localhost:8080/spring-social-security-demo-webapp/signin/google" method="POST">
    <p><input type="submit" value="Login with Google" /></p>
</form> 
</authz:authorize>

 <authz:authorize access="hasRole('ROLE_USER')">

    You are already logged in

 </authz:authorize>
 </body>
 </html>

enter image description here

最佳答案

使用 spring-social 通过 oauth 登录 google 时,需要执行以下操作

    <form name="go_signin" id="go_signin" action="<c:url value="/signin/google"/>" method="POST">
    <button type="submit">Sign In with Google</button>
    <input type="hidden" name="scope" value="https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo#email https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/tasks https://www-opensocial.googleusercontent.com/api/people" />
</form>

这是一篇探讨类似问题的帖子 http://forum.spring.io/forum/spring-projects/web/social/120358-error-400-with-spring-social-google

Linkedin "Scope" Variable not set

关于java - 使用 Google 以及 Spring Security 和 Spring Social 登录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28765444/

相关文章:

java - 当可以导入 java 类时为什么要使用依赖注入(inject)?

java - Spring 安全: Cannot resolve reference to bean while setting constructor argument

java - 使用 Mockito 模拟 lombok @Getter 字段

java - 如何在 Java 中比较字符串?

java - 将 getResource 与 ProGuard 一起使用会导致空结果

java - 在 Spring 中使用 Web Sockets 创建 Activity 提要

java - 如何检查 Java 类是否是当前堆栈跟踪的一部分?

java - 如果 pom.xml 文件有错误,创建 Maven 项目时可能会出现什么问题

使用java配置的spring security自定义过滤器

spring - 使用 Spring 3.0.5 和 Jackson 向 Tomcat 发出 JSON PUT 请求时出现 403