1

所以我试图向我的 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;
 }

 }
4

1 回答 1

3

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

另一个问题是您使用<authentication-manager/>了两次而没有为其中任何一个提供明确的“id =”,这实际上具有仅定义一个的效果,AuthenticationManager因为第二个覆盖了第一个(它们都具有相同的 id)。尝试使用“id=”而不是“alias=”。

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

于 2014-04-18T17:59:49.773 回答