我正在使用带有 authorization_code流和 @EnableZuulProxy 的spring-boot-oauth2。我跟随tut-spring-security-and-angular-js with oauth2中的示例。 为开发目的,我将 access_token_validty 设置为60秒。 Everythings工作正常,直到访问令牌仍然有效。但是当访问令牌过期时(我等了一会儿就过期了),我得到了例外,如下所示..
WARN SendErrorFilter:78 Error during filtering
com.netflix.zuul.exception.ZuulException: Filter threw Exception
at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:227)
at com.netflix.zuul.FilterProcessor.runFilters(FilterProcessor.java:157)
at com.netflix.zuul.FilterProcessor.preRoute(FilterProcessor.java:133)
at com.netflix.zuul.ZuulRunner.preRoute(ZuulRunner.java:105)
at com.netflix.zuul.http.ZuulServlet.preRoute(ZuulServlet.java:125)
at com.netflix.zuul.http.ZuulServlet.service(ZuulServlet.java:74)
at org.springframework.web.servlet.mvc.ServletWrappingController.handleRequestInternal(ServletWrappingController.java:157)
at org.springframework.cloud.netflix.zuul.web.ZuulController.handleRequest(ZuulController.java:44)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:50)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:116)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:110)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:116)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at com.t3k.products.t3k_portal.backend.config.SecurityConfig$1.doFilterInternal(SecurityConfig.java:112)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:124)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter.doFilter(OAuth2ClientContextFilter.java:60)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter.doFilter(OAuth2ClientContextFilter.java:60)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.security.authentication.BadCredentialsException: Cannot obtain valid access token
at org.springframework.cloud.security.oauth2.proxy.OAuth2TokenRelayFilter.getAccessToken(OAuth2TokenRelayFilter.java:99)
at org.springframework.cloud.security.oauth2.proxy.OAuth2TokenRelayFilter.run(OAuth2TokenRelayFilter.java:79)
at com.netflix.zuul.ZuulFilter.runFilter(ZuulFilter.java:112)
at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:193)
... 102 more
我使用的是spring-boot 1.5.4版,我还将OAuth2RestTemplate配置为this github问题。任何建议都会非常感激。
答案 0 :(得分:0)
正在使用相同的教程并在实现访问令牌刷新时遇到同样的问题。
Caused by: org.springframework.security.authentication.BadCredentialsException: Cannot obtain valid access token
at org.springframework.cloud.security.oauth2.proxy.OAuth2TokenRelayFilter.getAccessToken(OAuth2TokenRelayFilter.java:99) ~[spring-cloud-security-1.2.1.RELEASE.jar:1.2.1.RELEASE]
具体 - 当我收到错误时,我的测试应用程序被修改为使用通常的令牌,而不是JWT,但我认为解决问题并不重要。
澄清问题:
1)为客户添加密码授予:
@Configuration
@EnableAuthorizationServer
protected static class AuthServerConfig
extends AuthorizationServerConfigurerAdapter {
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("app0")
.secret("secret0")
.authorizedGrantTypes("authorization_code","refresh_token","password")
.scopes("some_scope");
}
2)通过curl执行以下请求(可以使用postman或其他首选实用程序)
curl -X POST \
http://localhost:9999/uaa/oauth/token \
-H 'authorization: Basic YXBwMDpzZWNyZXQw' \
-H 'content-type: multipart/form-data;' \
-F grant_type=password \
-F scope=some_scope \
-F username=john \
-F password=123
3)它返回
{
"access_token": "cc5fff72-8f09-4770-87f5-f2237ce5978f",
"token_type": "bearer",
"refresh_token": "da55eb5c-6d31-4d70-9af8-bad8ce8a777f",
"expires_in": 43199,
"scope": "some_scope"
}
4)获取refresh_token的值并在下一个curl命令
中使用它curl -X POST \
http://localhost:9999/uaa/oauth/token \
-H 'authorization: Basic YXBwMDpzZWNyZXQw' \
-H 'content-type: multipart/form-data;' \
-F grant_type=refresh_token \
-F scope=some_scope \
-F refresh_token=da55eb5c-6d31-4d70-9af8-bad8ce8a777f
5)得到答案:
{"error":"server_error","error_description":"UserDetailsService is required."}
使用错误说明可以轻松地found on GitHub
找到合适的解决方案和解释简单地说,有必要将UserDetailsService注入AuthorizationServerConfiguration并将其添加到AuthorizationServerEndpointsConfigurer配置中。例如:
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
如果在此修改后发生以下错误
***************************
APPLICATION FAILED TO START
***************************
Description:
Field userDetailsService in demo.AuthserverApplication$AuthServerConfig required a bean of type 'org.springframework.security.core.userdetails.UserDetailsService' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.security.core.userdetails.UserDetailsService' in your configuration.
这意味着auth服务器代码缺少显式定义的UserDetailsService(就像在问题中提到的原始教程一样)
出于测试目的,内存中的UserDetailsService bean可以像这样指定
@EnableResourceServer
public class AuthserverApplication extends WebMvcConfigurerAdapter {
@Bean
public UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("john").password("123").roles("USER").build());
manager.createUser(User.withUsername("ivan").password("123").roles("USER").build());
return manager;
}
答案 1 :(得分:0)
OAuth服务器调用用户详细信息查询,因此需要为UserDetailsService注入一个bean。在我的情况下,我能够通过LdapUserDetailsService获得这个,因为我的用户详细信息保存在LDAP中。
答案 2 :(得分:0)
作为tut-spring-security-and-angular-js的示例,我还有3个应用 UI , API 和 Auth 。我的 UI 应用程序有3种方案可以从我的 API 应用程序中获取数据。
对于案例1:我使用spring-oauth2 密码流和管理员帐户。所以我创建了以
的形式获取刷新令牌和访问令牌import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.Assert;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.joda.JodaModule;
import com.jayway.restassured.RestAssured;
import com.jayway.restassured.config.ObjectMapperConfig;
import com.jayway.restassured.mapper.factory.Jackson2ObjectMapperFactory;
import com.jayway.restassured.response.Response;
import com.jayway.restassured.specification.RequestSpecification;
@Configuration
public class RestServiceConfig implements InitializingBean {
private static final Logger applicationLogger = LogManager.getLogger("applicationLogs." + RestServiceConfig.class.getName());
private static String applicationResourceUrl;
private static String authServerTokenURI;
private static String authServerClientId;
private static String authServerClientSecret;
private static String rootUserName;
private static String rootUserSecret;
@Value("${security.oauth2.client.access-token-uri}")
public void setAuthServerTokenURI(String url) {
authServerTokenURI = url;
}
@Value("${security.oauth2.client.client-id}")
public void setAuthServerClientId(String clientId) {
authServerClientId = clientId;
}
@Value("${security.oauth2.client.client-secret}")
public void setAuthServerClientSecret(String secret) {
authServerClientSecret = secret;
}
@Value("${root-user.name}")
public void setRootUserName(String name) {
rootUserName = name;
}
@Value("${root-user.secret}")
public void setRootUserSecret(String secret) {
rootUserSecret = secret;
}
@Value("${api-server.application}/api/")
public void setApplicationResourceUrl(String url) {
applicationResourceUrl = url;
}
private static String refreshToken;
private static String accessToken;
public static final String createURL(String path) {
applicationLogger.info("Create REST service URI ==> " + applicationResourceUrl + path);
return applicationResourceUrl + path;
}
public static final Response processed(String url, HashMap<String, ?> headers, Object body, HttpMethod method) {
RequestSpecification request = getRestTemplate().contentType("application/json");
if (headers != null) {
request.headers(headers);
}
Response response = null;
switch (method) {
case POST: {
response = request.body(body).post(createURL(url));
break;
}
case PUT: {
response = request.body(body).put(createURL(url));
break;
}
case GET: {
response = request.get(createURL(url));
break;
}
case DELETE: {
response = request.body(body).delete(createURL(url));
break;
}
default:
break;
}
// if access-token has expired, obtained new one and resend current
// request
if (response.getStatusCode() == 401) {
accessToken = obtainAccessToken(refreshToken);
return processed(url, headers, body, method);
}
return response;
}
public static <T> T parse(Response response, Class<T> responseType) {
if (response.getStatusCode() != 200 || response.body().asString().equals("")) {
return null;
}
return response.getBody().as(responseType);
}
private static final RequestSpecification getRestTemplate() {
return RestAssured.given().header("Authorization", "Bearer " + accessToken);
}
private static final String obtainRootUserRefreshToken() {
applicationLogger.info("----- Generation New refresh-token for Root User -----");
final Map<String, String> params = new HashMap<String, String>();
params.put("grant_type", "password");
params.put("client_id", authServerClientId);
params.put("username", rootUserName);
params.put("password", rootUserSecret);
// @formatter:off
final Response response = RestAssured.given()
.auth().preemptive().basic(authServerClientId, authServerClientSecret)
.and()
.with().params(params)
.when().post(authServerTokenURI);
// @formatter:on
String refreshToken = response.jsonPath().getString("refresh_token");
applicationLogger.info("Obtained New Refresh Token ==> " + refreshToken);
Assert.notNull(refreshToken, "Failed for fetching Refresh Token. This problem can be caused by failed to connect Authetication server.");
return refreshToken;
}
private synchronized final static String obtainAccessToken(String refreshToken) {
applicationLogger.info("----- Generation New access-token for Root User with refresh-token[" + refreshToken + "] -----");
final Map<String, String> params = new HashMap<String, String>();
params.put("grant_type", "refresh_token");
params.put("client_id", authServerClientId);
params.put("refresh_token", refreshToken);
// @formatter:off
final Response response = RestAssured.given()
.auth().preemptive().basic(authServerClientId, authServerClientSecret)
.with().params(params)
.when().post(authServerTokenURI);
// @formatter:on
String accessToken = response.jsonPath().getString("access_token");
Assert.notNull(accessToken, "Failed for fetching Access Token. This problem can be caused by failed to connect Authetication server.");
return accessToken;
}
@Override
public void afterPropertiesSet() throws Exception {
// RestAssured.defaultParser = Parser.JSON;
RestAssured.config = RestAssured.config().objectMapperConfig(ObjectMapperConfig.objectMapperConfig().jackson2ObjectMapperFactory(new Jackson2ObjectMapperFactory() {
@SuppressWarnings("rawtypes")
@Override
public ObjectMapper create(Class cls, String charset) {
// create custom objectMapper to parse Joda DateTime for RestAssured
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JodaModule());
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
return objectMapper;
}
}));
refreshToken = obtainRootUserRefreshToken();
accessToken = obtainAccessToken(refreshToken);
}
}
以下是从我的 API 服务器
获取应用程序设置的示例代码public List<Setting> loadApplicationSettings() {
// @formatter:off
SettingCriteria criteria = new SettingCriteria();
criteria.setApplicationId(1234l);
criteria.setStatus(Status.ACTIVE);
final Response response = RestServiceConfig.processed(
"settings/search/list",
null,
criteria,HttpMethod.POST);
// @formatter:on
return Arrays.asList(response.getBody().as(Setting[].class));
}
对于案例2:我使用@EnableZuulProxy
作为tut-spring-security-and-angular-js。
注意:请勿将zuul映射设为公开映射。请参阅this answer。
对于案例3:我使用了spring-oauth2的Oauth2RestTemplate
作为
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Conditional;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.client.OAuth2RestOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@Service
public class OAuth2RestService {
private static final Logger serviceLogger = LogManager.getLogger("serviceLogs." + OAuth2RestService.class.getName());
@Autowired
private OAuth2RestOperations restTemplate;
public <T> T get(String url, Class<T> responseType, HttpHeader... headers) {
return processRestService(url, HttpMethod.GET, null, responseType, headers);
}
public <T> T post(String url, Object body, Class<T> responseType, HttpHeader... headers) {
return processRestService(url, HttpMethod.POST, body, responseType, headers);
}
public <T> T put(String url, Object body, Class<T> responseType, HttpHeader... headers) {
return processRestService(url, HttpMethod.PUT, body, responseType, headers);
}
public <T> T delete(String url, Object body, Class<T> responseType, HttpHeader... headers) {
return processRestService(url, HttpMethod.DELETE, body, responseType, headers);
}
private <T> T processRestService(String url, HttpMethod method, Object body, Class<T> responseType, HttpHeader... headers) {
serviceLogger.info("Request URL [ " + url + " ] | Request Method [ " + method.name() + " ] | Expected Response-Type [ " + responseType + " ]");
try {
MultiValueMap<String, String> headerInfos = null;
if (headers != null && headers.length > 0) {
headerInfos = new LinkedMultiValueMap<String, String>();
for (HttpHeader header : headers) {
headerInfos.add(header.getName(), header.getValue().toString());
}
}
RequestEntity<Object> requestEntity = new RequestEntity<Object>(body, headerInfos, method, new URI(RestServiceConfig.createURL(url)));
ResponseEntity<T> response = restTemplate.exchange(requestEntity, responseType);
if (response.getStatusCode() == HttpStatus.OK) {
return response.getBody();
}
}
catch (URISyntaxException e) {
e.printStackTrace();
}
return null;
}
}
我们必须将OAuth2RestOperations
配置为自己。
@Configuration
public class AppConfig {
@Bean
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
@Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
public OAuth2RestOperations oAuth2RestOperations(OAuth2ProtectedResourceDetails details, OAuth2ClientContext oauth2ClientContext) {
OAuth2RestTemplate oAuth2RestTemplate = new OAuth2RestTemplate(details, oauth2ClientContext);
return oAuth2RestTemplate;
}
}
HttpHeader类
public class HttpHeader {
private String name;
private Object value;
public HttpHeader(String name, Object value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
以下是使用Oauth2RestService
类
@Controller
@RequestMapping("/company")
public class CompanyController extends BaseController {
@Autowired
private OAuth2RestService restService;
@GetMapping
public String company(Model model) {
CompanyCriteria criteria = new CompanyCriteria();
criteria.setWithStaticContent(true);
criteria.setWithSubKey(true);
List<CompanyBean> companies = Arrays.asList(restService.post("company/search/list", criteria, CompanyBean[].class));
model.addAttribute("companies", companies);
return "home_page";
}
}
另一个api电话
.....
UserCriteria criteria = new UserCriteria();
criteria.setEmail(email);
HashMap<String, Object> myHeaders = new HashMap<>();
myHeaders.put("key", "value");
restService.put("user/search", criteria, Long.class, new HttpHeader("someHeaders", myHeaders));
如果不是为了获取单个用户并发的访问令牌,那么Everythings工作正常。
例如,在执行客户端请求之前,我为每个请求提供了一些过滤器,这些请求是从我的 API 服务器获取一些数据。但是我从客户端获得了JQuery ajax调用方法,这些方法是异步运行的。在这种情况下,我的过滤器也会运行异步,当我的密码流的管理员帐户的访问令牌已过期时,这会出错。
见线程Concurrency problems refreshing OAuth2 tokens。所以我在现有过期时获取新访问令牌的方法中添加了synchronized
。
我希望对你有所帮助。如果您从我的代码中发现了一些弱点或代码,请不要费心去纠正我。