Spring Security Oauth2资源所有者密码流:当我发送REST请求时,我的用户详细信息服务始终获取客户端ID而不是用户名

时间:2014-04-18 16:22:36

标签: spring spring-security oauth-2.0 spring-security-oauth2

所以我正在尝试向我的oauth服务器发送请求(没有标题): grant_type = password& username = blah& password = blah& client_id = blahblah。

我有2个身份验证管理器(一个用于客户端,另一个用于用户验证)。问题是,我的身份验证管理器都没有传递用户名进行验证。在这两种情况下,都使用client_id调用它们。我想要的是验证客户端和另一个验证用户。

我的bean配置如下:

 <http pattern="/oauth/token" create-session="stateless"  authentication-manager-ref="authenticationManager" xmlns="http://www.springframework.org/schema/security">
    <intercept-url pattern="/oauth/token" access="ROLE_USER" />
    <anonymous enabled="false" />
    <http-basic entry-point-ref="clientAuthenticationEntryPoint" />

    <custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />  

    <access-denied-handler ref="oauthAccessDeniedHandler" />
</http>


<!-- The OAuth2 protected resources are separated out into their own block so we can deal with authorization and error handling 
    separately. This isn't mandatory, but it makes it easier to control the behaviour. -->
<http pattern="/api/**" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint"
    access-decision-manager-ref="accessDecisionManager" xmlns="http://www.springframework.org/schema/security">
    <anonymous enabled="false" />
    <intercept-url pattern="/api" access="ROLE_USER,SCOPE_READ" />

    <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
    <access-denied-handler ref="oauthAccessDeniedHandler" />
</http>


<authentication-manager  alias="authenticationManager"  xmlns="http://www.springframework.org/schema/security">
    <sec:authentication-provider user-service-ref="clientDetailsUserService" />
    <sec:authentication-provider user-service-ref="customUserDetailService">
        <sec:password-encoder ref="passwordEncoder" />
    </sec:authentication-provider>
</authentication-manager>


<beans:bean id="customUserDetailService" class="com.cointraders.api.securities.UserDetailsServiceImpl" />


<beans:bean id="clientDetails" class="org.springframework.security.oauth2.provider.JdbcClientDetailsService">
    <beans:constructor-arg ref="dataSource" />
</beans:bean>

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

<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices">
    <oauth:refresh-token />
    <oauth:password authentication-manager-ref="authenticationManager"  />
</oauth:authorization-server>


<oauth:resource-server id="resourceServerFilter" resource-id="api" token-services-ref="tokenServices" />

<sec:global-method-security pre-post-annotations="enabled" proxy-target-class="true">
    <sec:expression-handler ref="oauthExpressionHandler" />
</sec:global-method-security>

<oauth:expression-handler id="oauthExpressionHandler" />

<oauth:web-expression-handler id="oauthWebExpressionHandler" />

<beans:bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    <beans:property name="realmName" value="api/" />
</beans:bean>



<beans:bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
    <beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>


<beans:bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.JdbcTokenStore">
    <beans:constructor-arg ref="dataSource" />
</beans:bean>


<beans:bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
    <beans:property name="tokenStore" ref="tokenStore" />
    <beans:property name="supportRefreshToken" value="true" />
    <beans:property name="clientDetailsService" ref="clientDetails" />
</beans:bean>

<beans:bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
    <beans:constructor-arg ref="clientDetails" />
</beans:bean>

<beans:bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />

<beans:bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    <beans:property name="realmName" value="api" />
</beans:bean>

这是我的Web.XML

    <!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
  <filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>contextAttribute</param-name>
        <param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring</param-value>
    </init-param>
</filter>

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

<servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/appServlet/*.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>/</url-pattern>
 </servlet-mapping>

我的用户详细信息服务类

 public class UserDetailsServiceImpl extends PersonServiceImpl implements
    UserDetailsService {

@Override
public UserDetails loadUserByUsername(String username)
        throws UsernameNotFoundException {

    UserDetails details = null;
    Specification<Person> specs = Specifications.where(PersonSpecification.equalsUserName(username));
    Person person = this.personRepository.findOne(specs);
    if(person!=null)
    {   
        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        authorities.add(new   SimpleGrantedAuthority(person.getRole().getRole().name()));
        details = new User(person.getUserName(), person.getPassword(), person.getActive(), false, false, false, authorities);
    }
    return details;
 }

 }

1 个答案:

答案 0 :(得分:3)

<authorization-server/>中,您尚未在AuthenticationManager授权类型中设置<password/>(因此它使用的是您已映射到客户端凭据的默认bean名称“authenticationManager” )。

另一个问题是你使用<authentication-manager/>两次而没有给出明确的“id =”,这实际上只能定义一个AuthenticationManager,因为第二个会覆盖第一个{{1}}两者都有相同的身份)。尝试使用“id =”而不是“alias =”。

如果可以,您确实需要在标头中发送客户端凭据(但您可能知道)。