Spring Security Oauth - 永远不会调用自定义UserDetailsS​​ervice

时间:2016-04-05 05:30:55

标签: java spring rest spring-security-oauth2

弹簧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:oauth="http://www.springframework.org/schema/security/oauth2"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:sec="http://www.springframework.org/schema/security"
  xmlns:mvc="http://www.springframework.org/schema/mvc"
  xsi:schemaLocation="
http://www.springframework.org/schema/security/oauth2   http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd ">

  <!-- Default url to get a token from OAuth -->
  <http pattern="/api/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">

    <csrf disabled="true"/>
    <intercept-url pattern="/api/oauth/token" access="isFullyAuthenticated()"/>
    <anonymous enabled="false"/>
    <http-basic entry-point-ref="clientAuthenticationEntryPoint"/>

    <custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER"/>
    <access-denied-handler ref="oauthAccessDeniedHandler"/>
  </http>

  <!-- Protected sources  -->
  <http pattern="/api/services/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint" access-decision-manager-ref="accessDecisionManager" xmlns="http://www.springframework.org/schema/security" use-expressions="true">
    <anonymous enabled="false"/>
    <intercept-url pattern="/api/**" access="hasRole('ROLE_APP')"/>
    <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER"/>
    <access-denied-handler ref="oauthAccessDeniedHandler"/>
  </http>

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

  <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.oauth2.provider.vote.ScopeVoter"/>
        <bean class="org.springframework.security.access.vote.RoleVoter"/>
        <bean class="org.springframework.security.web.access.expression.WebExpressionVoter"/>
      </list>
    </constructor-arg>
  </bean>

  <authentication-manager id="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
    <authentication-provider user-service-ref="clientDetailsUserService"/>
  </authentication-manager>

  <sec:authentication-manager>
    <sec:authentication-provider user-service-ref='userDetailsServiceImpl'/>
  </sec:authentication-manager>

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

  <authentication-manager alias="authenticationManager" xmlns="http://www.springframework.org/schema/security">
    <authentication-provider user-service-ref="userDetailsServiceImpl"></authentication-provider>
  </authentication-manager>

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

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

  <bean id="oAuth2RequestFactory" class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
    <constructor-arg ref="clientDetails"/>
  </bean>

  <bean id="userApprovalHandler" class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
    <property name="tokenStore" ref="tokenStore"/>
    <property name="requestFactory" ref="oAuth2RequestFactory"/>
  </bean>

  <bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    <property name="realmName" value="test/client"/>
    <property name="typeName" value="Basic"/>
  </bean>

  <bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    <property name="realmName" value="test/client"/>
    <property name="typeName" value="Basic"/>
  </bean>

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

  <oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices" user-approval-handler-ref="userApprovalHandler">
    <oauth:authorization-code/>
    <oauth:implicit/>
    <oauth:refresh-token/>
    <oauth:client-credentials/>
    <oauth:password/>
  </oauth:authorization-server>

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

  <bean id="clientDetails" class="com.xxxxxx.service.ClientService"></bean>

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

UserServiceImpl

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private OauthRepository oauthRepository;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        User user = oauthRepository.getByUsername(s);
        return user;
    }

}

ClientServiceImpl

@Component
public class ClientService implements ClientDetailsService {

    @Autowired
    private OauthRepository oauthRepository;

    @Override
    public ClientDetails loadClientByClientId(String s) throws ClientRegistrationException {
        BaseClientDetails clientDetails = oauthRepository.getByClientId(s);
        return clientDetails;
    }
}

我一直在搜索,但我无法弄清楚为什么UserServiceImpl没有被调用。我进行了debbuged并且始终调用ClientServiceImpl来获取客户端和用户。 在向/api/oauth/token发送请求后,使用适当的参数(用户和客户端存储在数据库中),我得到:

{"error":"unauthorized","error_description":"Incorrect result size: expected 1, actual 0"}

我正在使用 - Spring Framework 4.2.5.RELEASE - Spring Mvc 4.2.5.RELEASE, - Spring Security 4.1.0.RC1, - Spring Security Oauth2 2.0.9.RELEASE

2 个答案:

答案 0 :(得分:0)

我认为你做的很好但是在

@Service public class UserDetailsServiceImpl implements UserDetailsService

您应该设置用户的密码及其角色。

请在此处查看代码

@Override
public UserDetails loadUserByUsername(String username)
        throws UsernameNotFoundException, DataAccessException
{
    System.out.println("Getting access details from Database !!");

    // Ideally it should be fetched from database and populated instance of
    // #org.springframework.security.core.userdetails.User should be returned from this method
    UserDetails user = new User(username, "password", true, true, true, true, new GrantedAuthority[]{ new GrantedAuthorityImpl("ROLE_USER") });
    return user;
}

UserDetailsS​​ervice接口用于查找任何给定用户的用户名,密码和GrantedAuthorities。该接口只提供了一个实现类需要实现的方法。

答案 1 :(得分:0)

我通过spring-security.xml中的以下更改解决了这个问题:

<!-- Default url to get a token from OAuth -->
<http pattern="/api/oauth/token" create-session="stateless"
      authentication-manager-ref="authenticationManager"
                      :

  <authentication-manager id="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
    <authentication-provider user-service-ref="userDetailsServiceImpl"/>
</authentication-manager>

我想我有两个authenticationMangager实例。不管怎样,谢谢。