使用授权类型“client_credentials”时OAuth2身份验证失败

时间:2017-06-05 10:15:33

标签: java spring-boot spring-security-oauth2

我使用OAuth2创建了一个授权服务器,目前,我可以在调用时获取一个持有者令牌:

 public class Anything<T>
    {
        /// <summary>
        /// Generic typed constructor
        /// </summary>
        /// <param name="param1"></param>
        public Anything(T param1)
        {
            Console.WriteLine("I'm generic typed constructor");
        }

        /// <summary>
        /// String typed constructor
        /// </summary>
        /// <param name="param1"></param>
        public Anything(string param1)
        {
            Console.WriteLine("I'm string typed constructor");
        }
    }

我使用返回的令牌并向资源服务器发出请求,如下所示:

POST /oauth/token?grant_type=client_credentials&amp;client_id=user-service&amp;client_secret=userServicePassword&amp;scope=server HTTP/1.1
Host: localhost:1002
Content-Type: application/json
Authorization: Basic dXNlci1zZXJ2aWNlOnVzZXJTZXJ2aWNlUGFzc3dvcmQ=

但是我得到了

POST /users/create HTTP/1.1
Host: localhost:1002
Content-Type: application/json
Authorization: Bearer 7ba026a4-2ae2-46be-8bd6-65d4aeb09dac
{
    "username":"nicolasmanic",
    "password":"12345",
    "authorities":["ADMIN", "USER"]
}

我的OAuth2AuthorizationConfig

{
  "timestamp": 1496657103659,
  "status": 403,
  "error": "Forbidden",
  "exception": "org.springframework.security.access.AccessDeniedException",
  "message": "Access Denied",
  "path": "/users/create"
}

我的WebSecurityConfig

@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter {

    private static final String STORY_SERVICE_PASSWORD = "storyServicePassword";
    private static final String USER_SERVICE_PASSWORD = "userServicePassword";

    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserService userService;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                .tokenStore(new InMemoryTokenStore())
                .authenticationManager(authenticationManager) //Enable password grant type.
                .userDetailsService(userService);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        clients.inMemory()
                .withClient("browser")
                .authorizedGrantTypes("refresh_token", "password")
                .scopes("ui")
                .and()
                .withClient("story-service")
                .secret(STORY_SERVICE_PASSWORD)
                .authorizedGrantTypes("client_credentials", "refresh_token")
                .scopes("server")
                .and()
                .withClient("user-service")
                .secret(USER_SERVICE_PASSWORD)
                .authorizedGrantTypes("client_credentials", "refresh_token")
                .scopes("server");
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer
                .tokenKeyAccess("permitAll()")
                .checkTokenAccess("isAuthenticated()");
    }
}

最后我的控制器

@Configuration
@Order(101)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

        @Autowired
        private UserService userDetailsService;

        /*
        * Authenticate all urls except from home {/} and /login/* etc.
        * */
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable()
                    .authorizeRequests()
                    .antMatchers("/","/login").permitAll();
        }

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService)
                    .passwordEncoder(new BCryptPasswordEncoder());
        }

        @Override
        @Bean
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }

你知道我的配置错误吗?

修改

此处还有stacktrace:

@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping(value = "/current", method = RequestMethod.GET)
    public Principal getUser(Principal principal) {
        return principal;
    }

    @PreAuthorize("#oauth2.hasScope('server')")
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public void createUser(@Valid @RequestBody User user) {
        userService.create(user);
    }
}

2 个答案:

答案 0 :(得分:1)

您必须将@EnableGlobalMethodSecurity添加到OAuth2AuthorizationConfig类。

答案 1 :(得分:0)

终于明白了。

我已完成删除 WebSecurityConfig 。我将 GlobalAuthenticationConfigurerAdapter 扩展为:

@Configuration
public class GlobalAuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter {

    @Autowired
    UserRepository userRepository;

    @Autowired
    UserServiceImpl userService;

    @Override
    public void init(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService());
        auth.authenticationProvider(authProvider());
    }

    @Bean
    public DaoAuthenticationProvider authProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userService);
        authProvider.setPasswordEncoder(new BCryptPasswordEncoder());
        return authProvider;
    }

    @Bean
    UserDetailsService userDetailsService() {
        return (username) -> userRepository
                .findByUsername(username);
    }
}

我认为该问题与 userService 自动装配有关。我曾经将它自动装入接口而不是实现 UserDetailsS​​ervice 的具体类(userServiceImpl)。