Java 弹簧OAuth2“;访问此资源需要完全身份验证”;

Java 弹簧OAuth2“;访问此资源需要完全身份验证”;,java,spring,authentication,spring-security-oauth2,Java,Spring,Authentication,Spring Security Oauth2,我正在尝试将SpringOAuth2用于我的rest应用程序。 但看起来我犯了一个错误,我能找到我犯的错误。 流程应为: 1.使用用户名和密码从/oauth/token获取令牌 2.使用提供的令牌向/security发出请求 MethodSecurityConfig: @Configuration @EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true) public class MethodSecur

我正在尝试将SpringOAuth2用于我的rest应用程序。 但看起来我犯了一个错误,我能找到我犯的错误。 流程应为: 1.使用用户名和密码从/oauth/token获取令牌 2.使用提供的令牌向/security发出请求

MethodSecurityConfig:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

    @Autowired
    private SecurityConfiguration securityConfig;

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        return new OAuth2MethodSecurityExpressionHandler();
    }
}
OAuth2ServerConfig:

@Configuration
public class OAuth2ServerConfig {

    private static final String RESOURCE_ID = "nessnity";

    @Configuration
    @Order(10)
    protected static class UiResourceConfiguration extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .requestMatchers().antMatchers("/security")
                    .and()
                    .authorizeRequests()
                    .antMatchers("/security").access("hasRole('USER')");
        }
    }

    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

        @Override
        public void configure(ResourceServerSecurityConfigurer resources) {
            resources.resourceId(RESOURCE_ID);
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {
            http
                    .requestMatchers().antMatchers("/security/")
                    .and()
                    .authorizeRequests()
                    .antMatchers("/security").access("#oauth2.hasScope('read')");
      }

    }

    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

        @Autowired
        private TokenStore tokenStore;

        @Autowired
        private UserApprovalHandler userApprovalHandler;

        @Autowired
        private AuthenticationManager authenticationManager;

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.inMemory()
                    .withClient("my-client")
                    .resourceIds(RESOURCE_ID)
                    .authorizedGrantTypes("client_credentials")
                    .authorities("ROLE_CLIENT")
                    .scopes("read")
                    .secret("password")
                    .accessTokenValiditySeconds(60);
        }

        @Bean
        public TokenStore tokenStore() {
            return new InMemoryTokenStore();
        }

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints
                    .tokenStore(tokenStore)
                    .userApprovalHandler(userApprovalHandler)
                    .authenticationManager(authenticationManager);
        }

        @Override
        public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
            oauthServer.realm("sparklr2/client");
        }

    }

    protected static class Stuff {

        @Autowired
        private ClientDetailsService clientDetailsService;

        @Autowired
        private TokenStore tokenStore;

        @Bean
        public ApprovalStore approvalStore() throws Exception {
            TokenApprovalStore store = new TokenApprovalStore();
            store.setTokenStore(tokenStore);
            return store;
        }

        @Bean
        @Lazy
        @Scope(proxyMode=ScopedProxyMode.TARGET_CLASS)
        public SparklrUserApprovalHandler userApprovalHandler() throws Exception {
            SparklrUserApprovalHandler handler = new SparklrUserApprovalHandler();
            handler.setApprovalStore(approvalStore());
            handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
            handler.setClientDetailsService(clientDetailsService);
            handler.setUseApprovalStore(true);
            return handler;
        }
    }

}
证券配置:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("root")
                .password("password")
                .roles("USER");
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/oauth/uncache_approvals", "/oauth/cache_approvals");
    }

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .anyRequest().hasRole("USER");
    }
}
问题:当我试图获取令牌时

curl --user root:password --data "grant_type=client_credentials" http://localhost:8080/oauth/token
我得到消息:

{“错误”:“无效的客户端”,“错误描述”:“坏客户端” 凭证“}

第二个问题是如何在url参数中传递用户名/密码,如/oauth/token?username=root&password=password

谢谢

更新

我决定从头开始,使用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"
       xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd

        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">


    <http pattern="/oauth/token" create-session="stateless"
          authentication-manager-ref="authenticationManager"
          xmlns="http://www.springframework.org/schema/security">
        <intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY"/>
        <anonymous enabled="false"/>
        <http-basic entry-point-ref="clientAuthenticationEntryPoint"/>
        <custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER"/>
        <access-denied-handler ref="oauthAccessDeniedHandler"/>
    </http>

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

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

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

    <bean id="clientDetails" class="com.nessnity.api.security.OAuthClienDetailsService">
        <property name="id" value="testuser"/>
        <property name="secretKey" value="secret" />
    </bean>

    <bean id="clientAuthenticationEntryPoint"
          class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
        <property name="realmName" value="springsec/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">
        <oauth:authorization-code/>
        <oauth:implicit/>
        <oauth:refresh-token/>
        <oauth:client-credentials/>
        <oauth:password authentication-manager-ref="userAuthenticationManager"/>
    </oauth:authorization-server>

    <authentication-manager id="userAuthenticationManager"
                            xmlns="http://www.springframework.org/schema/security">
        <authentication-provider ref="customUserAuthenticationProvider">
        </authentication-provider>
    </authentication-manager>

    <bean id="customUserAuthenticationProvider"
          class="com.nessnity.api.security.OAuthUserAuthenticationProvider">
    </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="900000000"/>
        <property name="clientDetailsService" ref="clientDetails"/>
    </bean>

    <bean id="tokenStore"
          class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore"/>

    <bean id="oauthAuthenticationEntryPoint"
          class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    </bean>

    <http pattern="/resources/**" create-session="never"
          entry-point-ref="oauthAuthenticationEntryPoint"
          xmlns="http://www.springframework.org/schema/security">
        <anonymous enabled="false"/>
        <intercept-url pattern="/resources/**" method="GET"/>
        <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER"/>
        <access-denied-handler ref="oauthAccessDeniedHandler"/>
    </http>

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

</beans>

我遇到过类似的问题,在做了以下更改后,它仍然有效

在AuthorizationServerConfiguration类中,替换

        @Override
        public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
            oauthServer.realm("sparklr2/client");
        }
用下面的代码

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        //oauthServer.realm("sparklr2/client");
        oauthServer.allowFormAuthenticationForClients();
    }
请求应该是这样的

/oauth/token?授权类型=密码&范围=读+写&客户端id=客户端id&客户端密码=密码&用户名=用户名&密码=密码


在访问令牌请求中,您正在使用客户端凭据授予类型。OAuth规范指出,如果是客户端\u凭据授予类型,则需要提供base64编码的
客户端\u id:client\u secret
作为基本授权头。 例如,如果您的客户id为
google
,客户机密为
x23r-ss56-rfg8-6yt6
,那么您需要将这些字符串添加为
google:x23r-ss56-rfg8-6yt6
,使用Base64编码器对其进行编码,并根据需要发出请求


curl--header“Authorization:Basic”--data“grant\u type=client\u credentials”http://localhost:8080/oauth/token
我在任何地方都看不到
/oauth/token
的任何配置。永远不要在参数中传递敏感信息,如用户名和密码;它们会保存在历史记录之类的文件中。@chrylis我希望它在默认情况下可用。。来自spring oauth文档:“TokenEndpoint用于为访问令牌的请求提供服务。默认URL:/oauth/token。”。我错了吗?您是否试图使用Spring安全性来保护该端点?如果不是,您打算如何将用户的凭据输入端点处理器,这一点不清楚。@chrylis是的,我不清楚。我应该手动设置此端点还是默认情况下可用?这是第二个问题。我回顾了spring oauth示例Spark/tonr,但仍然不理解它是如何工作的。特别是使用代币流动。