Spring boot #oauth2.hasScope弹簧靴+;钥匙斗篷

Spring boot #oauth2.hasScope弹簧靴+;钥匙斗篷,spring-boot,keycloak,spring-security-oauth2,Spring Boot,Keycloak,Spring Security Oauth2,我想在spring boot+KeyClope中使用#oauth2.hasScope,获取带有grant_type=client_凭证的令牌。但它不起作用。这是我的密码,你能帮我吗 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId>

我想在spring boot+KeyClope中使用#oauth2.hasScope,获取带有grant_type=client_凭证的令牌。但它不起作用。这是我的密码,你能帮我吗

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.security.oauth</groupId>
        <artifactId>spring-security-oauth2</artifactId>
        <version>2.3.7.RELEASE</version>
    </dependency>
这是我的控制器 hasAnyAuthority(“范围电话”)可以,但“oauth2.hasScope”(“电话”)或“oauth2.hasScope”(“范围电话”)不工作,我收到403禁止

@RequestMapping(value = "/user", method = RequestMethod.GET)
    @PreAuthorize("hasAnyAuthority('SCOPE_phone')")
    public ResponseEntity<String> getUser() {
        return ResponseEntity.ok("Hello User");
    }

    @RequestMapping(value = "/all-user", method = RequestMethod.GET)
    @PreAuthorize("#oauth2.hasScope('phone')")
    public ResponseEntity<String> getAllUser() {
        return ResponseEntity.ok("Hello All User");
}

您是否使用KeyClope作为授权服务器?您有用于RemoteTokenServices的bean吗?
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        return getOAuth2MethodSecurityExpressionHandler();
    }

    /**
     *A security expression handler that can handle default method security expressions plus the set provided by OAuth2SecurityExpressionMethods using the variable oauth2 to access the methods. For example, the expression #oauth2.clientHasRole('ROLE_ADMIN') would invoke OAuth2SecurityExpressionMethods.clientHasRole(java.lang.String)
     *By default the OAuth2ExpressionParser is used. If this is undesirable one can inject their own ExpressionParser using AbstractSecurityExpressionHandler.setExpressionParser(ExpressionParser).
     */
    @Bean
    public OAuth2MethodSecurityExpressionHandler getOAuth2MethodSecurityExpressionHandler() {
        return new OAuth2MethodSecurityExpressionHandler();
    }

}

@RequestMapping(value = "/user", method = RequestMethod.GET)
    @PreAuthorize("hasAnyAuthority('SCOPE_phone')")
    public ResponseEntity<String> getUser() {
        return ResponseEntity.ok("Hello User");
    }

    @RequestMapping(value = "/all-user", method = RequestMethod.GET)
    @PreAuthorize("#oauth2.hasScope('phone')")
    public ResponseEntity<String> getAllUser() {
        return ResponseEntity.ok("Hello All User");
}
{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI1MkRsOVNTMlREY0M5SkFtZmZ3ZE1BNjJkbFBreDlFMDdRSnhObF9sVDNJIn0.eyJleHAiOjE2MDM3ODQzNTMsImlhdCI6MTYwMzc4NDA1MywianRpIjoiY2Q2OWIzMDgtNDBmZi00YjJmLTljOWMtNjMyZjQxYTYyNzgwIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL21pY3Jvc2VydmljZSIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiIxZGExM2RjMy0yNDQ1LTRlZTQtYjFhNS0zNjc2YzYyMjY4OTciLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJtb2JpbGVyZXRhaWwiLCJzZXNzaW9uX3N0YXRlIjoiMmIxMzRlN2MtNDZiMS00MGNmLWIyMmYtODA3MDcyYWFjMGU0IiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsibW9iaWxlcmV0YWlsIjp7InJvbGVzIjpbInVtYV9wcm90ZWN0aW9uIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InBob25lIHByb2ZpbGUgZW1haWwiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImNsaWVudElkIjoibW9iaWxlcmV0YWlsIiwiY2xpZW50SG9zdCI6IjEyNy4wLjAuMSIsInByZWZlcnJlZF91c2VybmFtZSI6InNlcnZpY2UtYWNjb3VudC1tb2JpbGVyZXRhaWwiLCJjbGllbnRBZGRyZXNzIjoiMTI3LjAuMC4xIn0.acg7pPIK89AVFQT0oYrMmBwBGe4hy6PYrQCYdNbSOQA49p6FZ5ZCdqBtxKrxy2DYxgBJZNhMJ-PPZ_WrmRwTAS1H-Udo0Dj9o8VQLDyG2PsrVv8jdsCrrlSnPIg978HF6eP2bh49G4JYZjuLqzuX2h29voFWEMvtCjKGPYTwrwG24uYCKyEr_nCUV8_7Ky6hTyxl10xxnQ5qGjo1Acbhs-F4omgi6H2I2H17PUPVkKdeMKAbsVbubzbMbijgYAUf3j4KbsxEArJ6KC6ZZDsFIIB7-xMBMZD3OYjpn6-3Mt1s_QAlp4I9bdkSS2dNFtP3U6OmTnHCGyYgmScD8FTffw",
    "expires_in": 300,
    "refresh_expires_in": 1800,
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIxOGM5ZmRiNy1mNzQ0LTQ2ZjktODQ4Ni0wMTFjNWVkOWNkZDIifQ.eyJleHAiOjE2MDM3ODU4NTMsImlhdCI6MTYwMzc4NDA1MywianRpIjoiMGJmOWMyZjItNjM5YS00OGVkLTgzNzUtM2M0YTE0ODc2ZGU0IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL21pY3Jvc2VydmljZSIsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9hdXRoL3JlYWxtcy9taWNyb3NlcnZpY2UiLCJzdWIiOiIxZGExM2RjMy0yNDQ1LTRlZTQtYjFhNS0zNjc2YzYyMjY4OTciLCJ0eXAiOiJSZWZyZXNoIiwiYXpwIjoibW9iaWxlcmV0YWlsIiwic2Vzc2lvbl9zdGF0ZSI6IjJiMTM0ZTdjLTQ2YjEtNDBjZi1iMjJmLTgwNzA3MmFhYzBlNCIsInNjb3BlIjoicGhvbmUgcHJvZmlsZSBlbWFpbCJ9.dG67rD5TPQLSQY69Fhdh9am_t_SZoiL9MEuufD6eOvU",
    "token_type": "bearer",
    "not-before-policy": 0,
    "session_state": "2b134e7c-46b1-40cf-b22f-807072aac0e4",
    "scope": "phone profile email"
}