Java 无法获取用户详细信息:类org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException,无法获取新的访问权限

Java 无法获取用户详细信息:类org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException,无法获取新的访问权限,java,spring-boot,spring-security,spring-cloud,Java,Spring Boot,Spring Security,Spring Cloud,我正在处理Spring Cloud小POC,并得到以下错误。我试图使用使用此方法获得的令牌访问资源。你能告诉我怎么了吗 无法获取用户详细信息:类org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException,无法获取资源“null”的新访问令牌。未将提供程序管理器配置为支持它 SecurityConfig @Configuration @EnableGlobalMethodSecurity(prePo

我正在处理Spring Cloud小POC,并得到以下错误。我试图使用使用此方法获得的令牌访问资源。你能告诉我怎么了吗

无法获取用户详细信息:类org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException,无法获取资源“null”的新访问令牌。未将提供程序管理器配置为支持它

SecurityConfig

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends GlobalMethodSecurityConfiguration {
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        return new OAuth2MethodSecurityExpressionHandler();
    }   
}
CustomUserInfoTokenServices

public class CustomUserInfoTokenServices implements ResourceServerTokenServices {

    protected final Log logger = LogFactory.getLog(getClass());

    private static final String[] PRINCIPAL_KEYS = new String[] { "user", "username",
            "userid", "user_id", "login", "id", "name" };

    private final String userInfoEndpointUrl;

    private final String clientId;

    private OAuth2RestOperations restTemplate;

    private String tokenType = DefaultOAuth2AccessToken.BEARER_TYPE;

    private AuthoritiesExtractor authoritiesExtractor = new FixedAuthoritiesExtractor();

    public CustomUserInfoTokenServices(String userInfoEndpointUrl, String clientId) {
        this.userInfoEndpointUrl = userInfoEndpointUrl;
        this.clientId = clientId;
    }

    public void setTokenType(String tokenType) {
        this.tokenType = tokenType;
    }

    public void setRestTemplate(OAuth2RestOperations restTemplate) {
        this.restTemplate = restTemplate;
    }

    public void setAuthoritiesExtractor(AuthoritiesExtractor authoritiesExtractor) {
        this.authoritiesExtractor = authoritiesExtractor;
    }

    @Override
    public OAuth2Authentication loadAuthentication(String accessToken)
            throws AuthenticationException, InvalidTokenException {
        Map<String, Object> map = getMap(this.userInfoEndpointUrl, accessToken);
        if (map.containsKey("error")) {
            this.logger.debug("userinfo returned error: " + map.get("error"));
            throw new InvalidTokenException(accessToken);
        }
        return extractAuthentication(map);
    }

    private OAuth2Authentication extractAuthentication(Map<String, Object> map) {
        Object principal = getPrincipal(map);
        OAuth2Request request = getRequest(map);
        List<GrantedAuthority> authorities = this.authoritiesExtractor
                .extractAuthorities(map);
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
                principal, "N/A", authorities);
        token.setDetails(map);
        return new OAuth2Authentication(request, token);
    }

    private Object getPrincipal(Map<String, Object> map) {
        for (String key : PRINCIPAL_KEYS) {
            if (map.containsKey(key)) {
                return map.get(key);
            }
        }
        return "unknown";
    }

    @SuppressWarnings({ "unchecked" })
    private OAuth2Request getRequest(Map<String, Object> map) {
        Map<String, Object> request = (Map<String, Object>) map.get("oauth2Request");

        String clientId = (String) request.get("clientId");
        Set<String> scope = new LinkedHashSet<>(request.containsKey("scope") ?
                (Collection<String>) request.get("scope") : Collections.<String>emptySet());

        return new OAuth2Request(null, clientId, null, true, new HashSet<>(scope),
                null, null, null, null);
    }

    @Override
    public OAuth2AccessToken readAccessToken(String accessToken) {
        throw new UnsupportedOperationException("Not supported: read access token");
    }

    @SuppressWarnings({ "unchecked" })
    private Map<String, Object> getMap(String path, String accessToken) {
        this.logger.info("Getting user info from: " + path);
        try {
            OAuth2RestOperations restTemplate = this.restTemplate;
            if (restTemplate == null) {
                BaseOAuth2ProtectedResourceDetails resource = new BaseOAuth2ProtectedResourceDetails();
                resource.setClientId(this.clientId);
                restTemplate = new OAuth2RestTemplate(resource);
            }
            OAuth2AccessToken existingToken = restTemplate.getOAuth2ClientContext()
                    .getAccessToken();
            if (existingToken == null || !accessToken.equals(existingToken.getValue())) {
                DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(
                        accessToken);
                token.setTokenType(this.tokenType);
                restTemplate.getOAuth2ClientContext().setAccessToken(token);
            }
            return restTemplate.getForEntity(path, Map.class).getBody();
        }
        catch (Exception ex) {
            this.logger.info("Could not fetch user details: " + ex.getClass() + ", "
                    + ex.getMessage());
            return Collections.<String, Object>singletonMap("error",
                    "Could not fetch user details");
        }
    }
公共类CustomUserInfoTokenServices实现ResourceServerTokenServices{
受保护的最终日志记录器=LogFactory.getLog(getClass());
私有静态最终字符串[]主体密钥=新字符串[]{“用户”、“用户名”,
“用户id”、“用户id”、“登录”、“id”、“名称”};
私有最终字符串userInfoEndpointUrl;
私有最终字符串clientId;
私有OAuth2RestOperations restTemplate;
私有字符串tokenType=DefaultOAuth2AccessToken.BEARER\u类型;
private Authorities Extractor Authorities Extractor=新的FixedAuthorities Extractor();
公共CustomUserInfoTokenServices(字符串userInfoEndpointUrl,字符串clientId){
this.userInfoEndpointUrl=userInfoEndpointUrl;
this.clientId=clientId;
}
公共void setTokenType(字符串tokenType){
this.tokenType=tokenType;
}
公共void setRestTemplate(OAuth2RestOperations restTemplate){
this.restTemplate=restTemplate;
}
public void setauthorities提取器(authorities提取器authorities提取器){
this.authoritiesExtractor=authoritiesExtractor;
}
@凌驾
公共OAuth2Authentication loadAuthentication(字符串访问令牌)
引发AuthenticationException,InvalidTokenException{
Map Map=getMap(this.userInfoEndpointUrl,accessToken);
if(map.containsKey(“错误”)){
this.logger.debug(“userinfo返回错误:”+map.get(“错误”));
抛出新的InvalidTokenException(accessToken);
}
返回身份验证(map);
}
私有OAuth2Authentication extractAuthentication(映射){
对象主体=getPrincipal(映射);
OAuth2Request请求=getRequest(映射);
列表权限=this.authorities提取器
.行政当局(地图);
UsernamePasswordAuthenticationToken=新的UsernamePasswordAuthenticationToken(
委托人,“不适用”,主管部门;
token.setDetails(map);
返回新的OAuth2Authentication(请求、令牌);
}
私有对象getPrincipal(映射){
for(字符串键:主键){
if(地图容器(图例)){
返回map.get(key);
}
}
返回“未知”;
}
@SuppressWarnings({“unchecked”})
私有OAuth2Request getRequest(映射){
映射请求=(Map)Map.get(“oauth2Request”);
String clientId=(String)request.get(“clientId”);
Set scope=newlinkedhashset(request.containsKey(“scope”)?
(Collection)request.get(“scope”):Collections.emptySet();
返回新的OAuth2Request(null,clientId,null,true,新的HashSet(scope),
空,空,空,空);
}
@凌驾
公共OAuth2AccessToken readAccessToken(字符串accessToken){
抛出新的UnsupportedOperationException(“不受支持:读取访问令牌”);
}
@SuppressWarnings({“unchecked”})
私有映射getMap(字符串路径、字符串访问令牌){
this.logger.info(“从:+路径获取用户信息”);
试一试{
OAuth2RestOperations restTemplate=this.restTemplate;
if(restTemplate==null){
BaseAuth2ProtectedResourceDetails资源=新的BaseAuth2ProtectedResourceDetails();
resource.setClientId(this.clientId);
restTemplate=新的OAuth2RestTemplate(资源);
}
OAuth2AccessToken existingToken=restTemplate.getOAuth2Client上下文()
.getAccessToken();
if(existingToken==null | |!accessToken.equals(existingToken.getValue())){
DefaultOAuth2AccessToken=新的DefaultOAuth2AccessToken(
accessToken);
token.setTokenType(this.tokenType);
restemplate.getOAuth2ClientContext().setAccessToken(令牌);
}
返回restemplate.getForEntity(path,Map.class).getBody();
}
捕获(例外情况除外){
this.logger.info(“无法获取用户详细信息:+ex.getClass()+”,”
+例如getMessage());
返回Collections.singletonMap(“错误”,
“无法获取用户详细信息”);
}
}
PluralsightSpringcloudM4SecureserviceApplication

@SpringBootApplication
@RestController
@EnableResourceServer
public class PluralsightSpringcloudM4SecureserviceApplication {

    public static void main(String[] args) {
        SpringApplication.run(PluralsightSpringcloudM4SecureserviceApplication.class, args);
    }

    // added
    @Autowired
    private ResourceServerProperties sso;

    // added
    @Bean
    public ResourceServerTokenServices myUserInfoTokenServices() {
        return new CustomUserInfoTokenServices(sso.getUserInfoUri(), sso.getClientId());
    }

    @RequestMapping("/tolldata")
    @PreAuthorize("#oauth2.hasScope('toll_read') and hasAuthority('ROLE_OPERATOR')")
    public ArrayList<TollUsage> getTollData() {

        TollUsage instance1 = new TollUsage("200", "station150", "B65GT1W", "2016-09-30T06:31:22");
        TollUsage instance2 = new TollUsage("201", "station119", "AHY673B", "2016-09-30T06:32:50");
        TollUsage instance3 = new TollUsage("202", "station150", "ZN2GP0", "2016-09-30T06:37:01");

        ArrayList<TollUsage> tolls = new ArrayList<TollUsage>();
        tolls.add(instance1);
        tolls.add(instance2);
        tolls.add(instance3);

        return tolls;
    }

    public class TollUsage {

        public String Id;
        public String stationId;
        public String licensePlate;
        public String timestamp;

        public TollUsage() {
        }

        public TollUsage(String id, String stationid, String licenseplate, String timestamp) {
            this.Id = id;
            this.stationId = stationid;
            this.licensePlate = licenseplate;
            this.timestamp = timestamp;
        }

    }
}
@springboot应用程序
@RestController
@EnableResourceServer
公共类PluralsightSpringcloudM4SecureserviceApplication{
公共静态void main(字符串[]args){
run(PluralsightSpringcloudM4SecureserviceApplication.class,args);
}
//增加
@自动连线
私有资源服务器属性;
//增加
@豆子
公共资源服务器令牌服务myUserInfoTokenServices(){
返回新的CustomUserInfoTokenServices(sso.getUserInfoUri(),sso.getClientId());
}
@请求映射(“/tolldata”)
@预授权(#oauth2.hasScope('toll_read')和hasAuthority('ROLE_OPERATOR'))
公共ArrayList getTollData(){
收费站实例1=新收费站(“200”、“150站”、“B65GT1W”、“2016-09-30T06:31:22”);
收费站实例2=新收费站(“201”、“车站119”、“AHY673B”、“2016-09-30T06:32:50”);
收费站实例3=新收费站(“202”,“站”