【问题标题】:How to allow anonymous twitter connections in an MVC configuration如何在 MVC 配置中允许匿名 Twitter 连接
【发布时间】:2016-01-11 17:48:25
【问题描述】:

使用 - 春季社交 1.1.4 - 春季社交推特 1.1.2 - 弹簧MVC-4.2 - 在tomcat 7上

下面是我的 MVC 应用程序的 tomcat 配置,包括 twitter 设置和 usersConnectionRepository。

这对于登录的 MVC 用户来说一切正常。

当我想允许客户端从非 MVC 身份验证用户可用的公共链接发送推文时,我的问题就出现了。 (#{request.userPrincipal.name} 将为空)

我看过很多例子。 大多数示例使用旧的 1.0.0 spring-social。 我注意到 spring-social-twitter 的新 1.1.2 版本没有零参数 Twitter() 构造函数,这在某些示例中被证明是一种无需 connectionRepository 的工作方式。

我正在寻找一种方法来配置或编码一个选项,以允许登录到我的应用程序的用户和匿名用户在我的网站上使用某些选项。

在下面的配置中,匿名用户被重定向到 connect/twitter 将导致获取 connetionRepository 的问题。 usersConnectionRepository 必须有一个“#{request.userPrincipal.name}”,因为我的 connectController 依赖于此。

我在想也许我需要一个自定义连接控制器... 必须有一个正确的方法来解决这个问题。

欢迎提出任何建议。

我的 web.xml

    <listener>
  <listener-class>
          org.springframework.web.util.Log4jConfigListener
      </listener-class>
</listener>


<display-name>Central Portal</display-name>

<context-param>  
    <param-name>spring.profiles.active</param-name>  
    <param-value>dev</param-value>  
</context-param>  
<context-param>  
    <param-name>spring.profiles.default</param-name>  
    <param-value>dev</param-value>  
</context-param>
<context-param>  
    <param-name>spring.liveBeansView.mbeanDomain</param-name>  
    <param-value>dev</param-value>  
</context-param> 

<!-- Spring MVC -->
<servlet> 
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<error-page>
    <error-code>500</error-code>
    <location>/WEB-INF//pages/error.jsp</location>
</error-page>

<error-page>
    <error-code>404</error-code>
    <location>/WEB-INF/pages/error.jsp</location>
</error-page>

<error-page>
    <location>/WEB-INF/pages/error.jsp</location>
</error-page>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/spring-security.xml,
        /WEB-INF/spring-database.xml   
    </param-value>
</context-param> 



<!-- Enable POST  --> 
<filter>
    <filter-name>hiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>hiddenHttpMethodFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>


<!-- Spring Security -->
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Concurrency listener -->
<listener>
    <listener-class>
        org.springframework.security.web.session.HttpSessionEventPublisher
    </listener-class>
</listener>

一点java配置

mvc-dispatcher-servlet.xml

<context:component-scan base-package="org.schoolit.usermanager.config" /> 

<!-- component-scan / controllers -->
<context:component-scan base-package="org.schoolit.webapplication.*" />
<context:component-scan base-package="org.schoolit.spring.social.*"/>

<!-- property-placeholder's  -->
<context:property-placeholder location="classpath:oauth.properties"/>

<!-- resource mapping  -->
<mvc:resources mapping="/gen/**" location="/WEB-INF/gen/" cache-period="31556926"/>
<mvc:resources mapping="/resources/**" location="/WEB-INF/resources/" cache-period="31556926"/>

<!-- JSP ViewResolver -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix">
        <value>/pages/</value>
    </property>
    <property name="suffix">
        <value>.jsp</value>
    </property>
</bean>

<!-- twitter stuff start --> 
<bean id="handlerExceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
        <props>
            <prop key="Exception">error</prop>
        </props>
    </property>
</bean> 

 <bean id="twitterTemplate" 
    class="org.springframework.social.twitter.api.impl.TwitterTemplate">
    <constructor-arg value="${twitter.oauth.consumerKey}"/>
    <constructor-arg value="${twitter.oauth.consumerSecret}"/>
<!--<constructor-arg value="${twitter.oauth.accessToken}"/>
    <constructor-arg value="${twitter.oauth.accessTokenSecret}"/>   --> 
</bean> 



<bean id="connectionFactoryLocator" class="org.springframework.social.connect.support.ConnectionFactoryRegistry">
    <property name="connectionFactories">
        <list>
            <bean class="org.springframework.social.twitter.connect.TwitterConnectionFactory">
                <constructor-arg value="${twitter.oauth.consumerKey}" />
                <constructor-arg value="${twitter.oauth.consumerSecret}" />          
            </bean>
        </list>
    </property>
</bean>  


<bean id="connectionRepository" factory-method="createConnectionRepository" factory-bean="usersConnectionRepository" scope="request">
    <constructor-arg value="#{request.userPrincipal.name}" />
    <aop:scoped-proxy proxy-target-class="true" />
</bean>

<bean id="usersConnectionRepository" 
      class="org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository">
    <constructor-arg ref="dataSource" />
    <constructor-arg ref="connectionFactoryLocator" />
    <constructor-arg ref="textEncryptor" />
</bean>

<bean id="textEncryptor" class="org.springframework.security.crypto.encrypt.Encryptors" 
            factory-method="noOpText" />

 <bean id="connectController" class="org.springframework.social.connect.web.ConnectController">
    <constructor-arg ref="connectionFactoryLocator"/>
    <constructor-arg ref="connectionRepository"/>
    <property name="applicationUrl" value="http://localhost:8080/CentralPortal/" />
    <property name="connectInterceptors">
            <list> 
                <bean class="org.schoolit.spring.social.TweetAfterConnectInterceptor"/>
            </list>
    </property> 
</bean>       

spring-database.xml

    <!-- App's dataSource used by jdbcTemplate,jdbc-user-service and connectController -->
<bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/spring_me" />
    <property name="username" value="root" />
    <property name="password" value="<mypassword>" />
</bean>

<!-- jdbcTemplate used in usermanager bit only for now. --> 
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
    <constructor-arg ref="dataSource" /> 
</bean>

spring-security.xml

  <!-- enable use-expressions -->
<http auto-config="true" use-expressions="true"> 

    <!-- Set up rolefilter's for requestmapping's -->
    <intercept-url pattern="/admin**" access="hasRole('ROLE_ADMIN')" />
    <intercept-url pattern="/usermanager**" access="hasRole('ROLE_ADMIN')" />  
    <intercept-url pattern="/users**" access="hasRole('ROLE_ADMIN')" />


    <!-- access denied page --> 
    <access-denied-handler error-page="/403" /> 
    <!-- loginform-setup Spring Security -->
    <form-login 
        login-page="/login" 
        default-target-url="/home" 
        login-processing-url="/j_spring_security_check"
        authentication-failure-url="/login?error" 
        username-parameter="username"
        password-parameter="password" /> 
    <logout logout-success-url="/login?logout"  />

    <!-- enable csrf protection default is enabled from 4.0 spring 
    <csrf /> <csrf disabled="true"/>  -->
     <csrf request-matcher-ref="connect/*" disabled="true"/>

    <!-- Prevent Clickjacking iframe's  --> 
    <headers>
        <frame-options policy="SAMEORIGIN"/> 
    </headers>  
    <!-- One login per username should be one set to 5 for testing-->
    <session-management>
        <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" expired-url="/login?error"   /> 
    </session-management>
</http>

<!-- Select users and user_roles from database -->
<authentication-manager>
    <authentication-provider>
    <password-encoder ref="encoder" />
        <jdbc-user-service data-source-ref="dataSource"
            users-by-username-query="select username,password, enabled from users where username=?"
            authorities-by-username-query="select username, role from user_roles where username =?  " />
    </authentication-provider>
</authentication-manager>

<!-- encoder bean. Used for password encryption -->
<beans:bean id="encoder" 
    class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
    <beans:constructor-arg name="strength" value="11" />
</beans:bean>

【问题讨论】:

    标签: java spring-mvc spring-social spring-social-twitter


    【解决方案1】:

    我看到你已经配置了twitterTemplate bean,如果你能够在应用程序中使用它,你就不需要做任何其他事情了。

    使用TwitterTemplate 而不是TwitterTwitterTemplate 实现了Twitter 接口,所以所有方法都可用。

    例子:

    //1. Search Twitter
    SearchResults results = twitterTemplate.searchOperations().search("#WinterIsComing");
    List<Tweet> tweets = results.getTweets();
    int i =0;
    for (Tweet tweet : tweets) {
        System.out.println(tweet.getUser().getName() + " Tweeted : "+tweet.getText() + " from " + tweet.getUser().getLocation() 
                + " @ " + tweet.getCreatedAt() + tweet.getUser().getLocation()  );
    }
    
    //2. Search Place by GeoLocation        
    RestTemplate restTemplate = twitterTemplate.getRestTemplate();
    GeoTemplate geoTemplate = new GeoTemplate(restTemplate, true, true);
    List<Place> place = geoTemplate.search(37.423021, -122.083739);
    for (Place p : place) {
        System.out.println(p.getName() + " " + p.getCountry() + " "+p.getId());
    }           
    
    //3. Get Twitter UserProfile
    TwitterProfile userProfile = twitterTemplate.userOperations().getUserProfile();
    System.out.println(userProfile.getName()+" has " +userProfile.getFriendsCount() + " friends");
    

    使用TwitterTemplate,用户无需登录。希望这会有所帮助!

    【讨论】:

    • 谢谢。我将尝试使用这个例子。我必须说,当我发布这篇文章时,我对整个春季社交活动的了解较少。必须说它的记录很差。尤其是较新的版本。
    • 是的,我同意。我也试图允许匿名访问,但由于缺乏适当的文档,我花了很长时间才意识到它是如何工作的。
    • 我认为问题出在 Spring.io 网站上。这些示例都依赖于 springboot autoconfig。如果您只是按照示例进行操作,您将永远不会看到或理解。我对此感到非常失望。
    • 是的,但是一旦您了解了 Spring Boot 及其自动配置,您就会发现它很棒。 PS:还在学习 Java Config n Spring boot。
    猜你喜欢
    • 1970-01-01
    • 2015-12-02
    • 2018-08-31
    • 1970-01-01
    • 2014-09-22
    • 1970-01-01
    • 2020-04-22
    • 2019-11-23
    • 2016-10-16
    相关资源
    最近更新 更多