Spring 如何使用OAuth2RestTemplate?

Spring 如何使用OAuth2RestTemplate?,spring,rest,spring-security,oauth,restapi,Spring,Rest,Spring Security,Oauth,Restapi,我试图理解如何使用OAuth2RestTemplate对象来使用我的OAuth2安全REST服务(它在不同的项目下运行,我们假设它也在不同的服务器上运行等等) 我的REST服务的一个例子是: http://localhost:8082/app/helloworld ->访问此URL会产生错误,因为我未通过身份验证 要请求令牌,我将转到: http://localhost:8082/app/oauth/token?grant_type=password&client_id=restapp

我试图理解如何使用OAuth2RestTemplate对象来使用我的OAuth2安全REST服务(它在不同的项目下运行,我们假设它也在不同的服务器上运行等等)

我的REST服务的一个例子是:

http://localhost:8082/app/helloworld
->访问此URL会产生错误,因为我未通过身份验证

要请求令牌,我将转到:

http://localhost:8082/app/oauth/token?grant_type=password&client_id=restapp&client_secret=restapp&username=**USERNAME**&password=**PASSWORD**
收到令牌后,我可以使用以下URL连接到RESTAPI(插入的令牌示例)

现在我的问题是如何实现第二个可以使用这个OAuth2安全RESTAPI的应用程序?我真的没有发现任何工作示例,其中您提供用户名和密码(例如,来自登录表单),然后生成一个令牌,可以重新使用该令牌从RESTAPI获取数据

我当前尝试了以下对象:

BaseOAuth2ProtectedResourceDetails baseOAuth2ProtectedResourceDetails =  new BaseOAuth2ProtectedResourceDetails();
baseOAuth2ProtectedResourceDetails.setClientId("restapp");
baseOAuth2ProtectedResourceDetails.setClientSecret("restapp");
baseOAuth2ProtectedResourceDetails.setGrantType("password");
// how to set user name and password ???

DefaultAccessTokenRequest accessTokenRequest = new DefaultAccessTokenRequest();
OAuth2ClientContext oAuth2ClientContext = new DefaultOAuth2ClientContext(accessTokenRequest());

OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(baseOAuth2ProtectedResourceDetails,oAuth2ClientContext);
但这根本不起作用:(


非常感谢您提供任何想法、工作示例或教程的链接。

您可以在此处找到编写OAuth客户端的示例:

在您的情况下,您不能对所有内容都使用默认类或基类,您有多个类实现了
OAuth2ProtectedResourceDetails
。配置取决于您如何配置OAuth服务,但假设您的curl连接,我建议您:

@EnableOAuth2Client
@Configuration
class MyConfig{

    @Value("${oauth.resource:http://localhost:8082}")
    private String baseUrl;
    @Value("${oauth.authorize:http://localhost:8082/oauth/authorize}")
    private String authorizeUrl;
    @Value("${oauth.token:http://localhost:8082/oauth/token}")
    private String tokenUrl;

    @Bean
    protected OAuth2ProtectedResourceDetails resource() {
        ResourceOwnerPasswordResourceDetails resource;
        resource = new ResourceOwnerPasswordResourceDetails();

        List scopes = new ArrayList<String>(2);
        scopes.add("write");
        scopes.add("read");
        resource.setAccessTokenUri(tokenUrl);
        resource.setClientId("restapp");
        resource.setClientSecret("restapp");
        resource.setGrantType("password");
        resource.setScope(scopes);
        resource.setUsername("**USERNAME**");
        resource.setPassword("**PASSWORD**");
        return resource;
    }

    @Bean
    public OAuth2RestOperations restTemplate() {
        AccessTokenRequest atr = new DefaultAccessTokenRequest();
        return new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(atr));
    }
}

@Service
@SuppressWarnings("unchecked")
class MyService {

    @Autowired
    private OAuth2RestOperations restTemplate;

    public MyService() {
        restTemplate.getAccessToken();
    }
}
@enableAuth2Client
@配置
类MyConfig{
@值(“${oauth.resource:http://localhost:8082}")
私有字符串baseUrl;
@值(“${oauth.authorize:http://localhost:8082/oauth/authorize}")
私有字符串地址;
@值(“${oauth.token:http://localhost:8082/oauth/token}")
私有字符串标记URL;
@豆子
受保护的OAuth2ProtectedResourceDetails资源(){
ResourceOwnerPasswordResourceDetails资源;
resource=新ResourceOwnerPasswordResourceDetails();
列表范围=新的ArrayList(2);
范围。添加(“写入”);
范围。添加(“读取”);
setAccessTokenUri(tokenUrl);
resource.setClientId(“restapp”);
resource.setClientSecret(“restapp”);
setGrantType(“密码”);
资源设置范围(范围);
resource.setUsername(“**用户名**”);
resource.setPassword(“**密码**”);
返回资源;
}
@豆子
公共OAuth2RestOperations restTemplate(){
AccessTokenRequest atr=新的DefaultAccessTokenRequest();
返回新的OAuth2RestTemplate(resource(),新的DefaultOAuth2ClientContext(atr));
}
}
@服务
@抑制警告(“未选中”)
类MyService{
@自动连线
私有OAuth2RestOperations restTemplate;
公共MyService(){
restTemplate.getAccessToken();
}
}
别忘了在你的配置类上设置
@enableAuth2Client
,我还建议你首先尝试使用curl,也尝试使用调试器跟踪它,因为由于安全原因,很多异常都被消耗掉了,而且从未打印出来,所以很难找到问题所在。你应该ld使用
记录器
并设置
调试
启用。 祝你好运

我在github上上传了springboot示例应用程序
描述您的情况,因为我找不到任何适用于您的场景的示例。

如果您想要访问令牌并使用标头中的访问令牌调用其他资源系统,我有不同的方法

Spring Security附带自动安全性:oauth2属性从application.yml文件访问每个请求,每个请求都有SESSIONID,它通过主体读取并提取用户信息,所以您需要确保在OAuthUser中注入主体,获取accessToken并调用资源服务器

这是您的application.yml,根据您的身份验证服务器进行更改:

security:
  oauth2:
    client:
      clientId: 233668646673605
      clientSecret: 33b17e044ee6a4fa383f46ec6e28ea1d
      accessTokenUri: https://graph.facebook.com/oauth/access_token
      userAuthorizationUri: https://www.facebook.com/dialog/oauth
      tokenName: oauth_token
      authenticationScheme: query
      clientAuthenticationScheme: form
    resource:
      userInfoUri: https://graph.facebook.com/me

@组件
公共类OAuthUser实现可序列化{
私有静态最终长serialVersionUID=1L;
私人字符串管理机构;
@杰索尼奥雷
私有字符串clientId;
@杰索尼奥雷
私有字符串grantType;
私有布尔值未验证;
private-Map userDetail=new-LinkedHashMap();
@杰索尼奥雷
私有字符串sessionId;
@杰索尼奥雷
私有字符串类型;
@杰索尼奥雷
私有字符串访问令牌;
@杰索尼奥雷
私人校长;
公共无效setOAuthUser(委托人){
this.principal=principal;
init();
}
公共主体getPrincipal(){
返还本金;
}
私有void init(){
if(主体!=null){
OAuth2Authentication OAuth2Authentication=(OAuth2Authentication)主体;
if(oAuth2Authentication!=null){
for(GrantedAuthority ga:oAuth2Authentication.getAuthority()){
setAuthority(ga.getAuthority());
}
setClientId(oAuth2Authentication.getOAuth2Request().getClientId());
setGrantType(oAuth2Authentication.getOAuth2Request().getGrantType());
setAuthenticated(oAuth2Authentication.getUserAuthentication().isAuthenticated());
OAuth2AuthenticationDetails OAuth2AuthenticationDetails=(OAuth2AuthenticationDetails)oAuth2Authentication
.getDetails();
if(oAuth2AuthenticationDetails!=null){
setSessionId(oAuth2AuthenticationDetails.getSessionId());
setTokenType(oAuth2AuthenticationDetails.getTokenType());
//这就是你要找的
setAccessToken(oAuth2AuthenticationDetails.getTokenValue());
}
//此详细信息与登录用户更相关
UsernamePasswordAuthenticationToken userAuthenticationToken=(UsernamePasswordAuthenticationToken)oAuth2Authentication.getUserAuthentication();
如果(userAuthenticationToken!=null){
LinkedHashMap detailMap=(LinkedHashMap)userAuthenticationToken.getDetails();
if(detailMap!=null){
对于(Map.Entry映射条目:detailMap.entrySet()){
security:
  oauth2:
    client:
      clientId: 233668646673605
      clientSecret: 33b17e044ee6a4fa383f46ec6e28ea1d
      accessTokenUri: https://graph.facebook.com/oauth/access_token
      userAuthorizationUri: https://www.facebook.com/dialog/oauth
      tokenName: oauth_token
      authenticationScheme: query
      clientAuthenticationScheme: form
    resource:
      userInfoUri: https://graph.facebook.com/me
@Component
public class OAuthUser implements Serializable {

private static final long serialVersionUID = 1L;

private String authority;

@JsonIgnore
private String clientId;

@JsonIgnore
private String grantType;
private boolean isAuthenticated;
private Map<String, Object> userDetail = new LinkedHashMap<String, Object>();

@JsonIgnore
private String sessionId;

@JsonIgnore
private String tokenType;

@JsonIgnore
private String accessToken;

@JsonIgnore
private Principal principal;

public void setOAuthUser(Principal principal) {
    this.principal = principal;
    init();
}

public Principal getPrincipal() {
    return principal;
}

private void init() {
    if (principal != null) {
        OAuth2Authentication oAuth2Authentication = (OAuth2Authentication) principal;
        if (oAuth2Authentication != null) {
            for (GrantedAuthority ga : oAuth2Authentication.getAuthorities()) {
                setAuthority(ga.getAuthority());
            }
            setClientId(oAuth2Authentication.getOAuth2Request().getClientId());
            setGrantType(oAuth2Authentication.getOAuth2Request().getGrantType());
            setAuthenticated(oAuth2Authentication.getUserAuthentication().isAuthenticated());

            OAuth2AuthenticationDetails oAuth2AuthenticationDetails = (OAuth2AuthenticationDetails) oAuth2Authentication
                    .getDetails();
            if (oAuth2AuthenticationDetails != null) {
                setSessionId(oAuth2AuthenticationDetails.getSessionId());
                setTokenType(oAuth2AuthenticationDetails.getTokenType());

            // This is what you will be looking for 
                setAccessToken(oAuth2AuthenticationDetails.getTokenValue());
            }

    // This detail is more related to Logged-in User
            UsernamePasswordAuthenticationToken userAuthenticationToken = (UsernamePasswordAuthenticationToken) oAuth2Authentication.getUserAuthentication();
            if (userAuthenticationToken != null) {
                LinkedHashMap<String, Object> detailMap = (LinkedHashMap<String, Object>) userAuthenticationToken.getDetails();
                if (detailMap != null) {
                    for (Map.Entry<String, Object> mapEntry : detailMap.entrySet()) {
                        //System.out.println("#### detail Key = " + mapEntry.getKey());
                        //System.out.println("#### detail Value = " + mapEntry.getValue());
                        getUserDetail().put(mapEntry.getKey(), mapEntry.getValue());
                    }

                }

            }

        }

    }
}


public String getAuthority() {
    return authority;
}

public void setAuthority(String authority) {
    this.authority = authority;
}

public String getClientId() {
    return clientId;
}

public void setClientId(String clientId) {
    this.clientId = clientId;
}

public String getGrantType() {
    return grantType;
}

public void setGrantType(String grantType) {
    this.grantType = grantType;
}

public boolean isAuthenticated() {
    return isAuthenticated;
}

public void setAuthenticated(boolean isAuthenticated) {
    this.isAuthenticated = isAuthenticated;
}

public Map<String, Object> getUserDetail() {
    return userDetail;
}

public void setUserDetail(Map<String, Object> userDetail) {
    this.userDetail = userDetail;
}

public String getSessionId() {
    return sessionId;
}

public void setSessionId(String sessionId) {
    this.sessionId = sessionId;
}

public String getTokenType() {
    return tokenType;
}

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

public String getAccessToken() {
    return accessToken;
}

public void setAccessToken(String accessToken) {
    this.accessToken = accessToken;
}

@Override
public String toString() {
    return "OAuthUser [clientId=" + clientId + ", grantType=" + grantType + ", isAuthenticated=" + isAuthenticated
            + ", userDetail=" + userDetail + ", sessionId=" + sessionId + ", tokenType="
            + tokenType + ", accessToken= " + accessToken + " ]";
}
@RestController
public class YourController {

@Autowired
OAuthUser oAuthUser;

// In case if you want to see Profile of user then you this 
@RequestMapping(value = "/profile", produces = MediaType.APPLICATION_JSON_VALUE)
public OAuthUser user(Principal principal) {
    oAuthUser.setOAuthUser(principal);

    // System.out.println("#### Inside user() - oAuthUser.toString() = " + oAuthUser.toString());

    return oAuthUser;
}


@RequestMapping(value = "/createOrder",
        method = RequestMethod.POST,
        headers = {"Content-type=application/json"},
        consumes = MediaType.APPLICATION_JSON_VALUE,
        produces = MediaType.APPLICATION_JSON_VALUE)
public FinalOrderDetail createOrder(@RequestBody CreateOrder createOrder) {

    return postCreateOrder_restTemplate(createOrder, oAuthUser).getBody();
}


private ResponseEntity<String> postCreateOrder_restTemplate(CreateOrder createOrder, OAuthUser oAuthUser) {

String url_POST = "your post url goes here";

    MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
    headers.add("Authorization", String.format("%s %s", oAuthUser.getTokenType(), oAuthUser.getAccessToken()));
    headers.add("Content-Type", "application/json");

    RestTemplate restTemplate = new RestTemplate();
    //restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());

    HttpEntity<String> request = new HttpEntity<String>(createOrder, headers);

    ResponseEntity<String> result = restTemplate.exchange(url_POST, HttpMethod.POST, request, String.class);
    System.out.println("#### post response = " + result);

    return result;
}


}
public ResourceOwnerPasswordResourceDetails() {
    setGrantType("password");
}
@EnableOAuth2Client
@Configuration
class MyConfig {

@Value("${security.oauth2.client.access-token-uri}")
private String tokenUrl;

@Value("${security.oauth2.client.client-id}")
private String clientId;

@Value("${security.oauth2.client.client-secret}")
private String clientSecret;

@Value("${security.oauth2.client.password-token}")
private String passwordToken;

@Value("${security.user.name}")
private String username;

@Value("${security.user.password}")
private String password;


@Bean
protected OAuth2ProtectedResourceDetails resource() {

    ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails();

    resource.setAccessTokenUri(tokenUrl);
    resource.setClientId(clientId);
    resource.setClientSecret(clientSecret);
    resource.setClientAuthenticationScheme(AuthenticationScheme.form);
    resource.setUsername(username);
    resource.setPassword(password + passwordToken);

    return resource;
}

@Bean
 public OAuth2RestOperations restTemplate() {
    return new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest()));
    }
}


@Service
@SuppressWarnings("unchecked")
class MyService {
    @Autowired
    private OAuth2RestOperations restTemplate;

    public MyService() {
        restTemplate.getAccessToken();
    }
}
spring.main.allow-bean-definition-overriding: true

security:
  oauth2:
    client:
      clientId: XXX
      clientSecret: XXX
      accessTokenUri: XXX
      tokenName: access_token
      grant-type: client_credentials
@SpringBootApplication
@EnableOAuth2Client
public class Main extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/").permitAll();
    }

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

    @Bean
    public OAuth2RestTemplate oauth2RestTemplate(ClientCredentialsResourceDetails details) {
        return new OAuth2RestTemplate(details);
    }

}
@RestController
class OfferController {

    @Autowired
    private OAuth2RestOperations restOperations;

    @RequestMapping(value = "/<your url>"
            , method = RequestMethod.GET
            , produces = "application/json")
    public String foo() {
        ResponseEntity<String> responseEntity = restOperations.getForEntity(<the url you want to call on the server>, String.class);
        return responseEntity.getBody();
    }
}
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.5.RELEASE</version>
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.security.oauth.boot</groupId>
        <artifactId>spring-security-oauth2-autoconfigure</artifactId>
        <version>2.1.5.RELEASE</version>
    </dependency>
</dependencies>