I have som old test that are calling some web services. There was no security on the webservice before. Now basic http authentication has been added to it and test are therefore failing. Test are using org.springframework.ws.test.server.MockWebServiceClient
example of test:
#Autowired
MockWebServiceClient mockClient
def "import valid entity"() {
setup:
def request = loadEntitesToRequest(validEntityFile)
Source requestPayload = createStringSourceFromObject(request)
when: 'Endpoint is requested to import valid entity'
mockClient.sendRequest(withPayload(requestPayload)).andExpect(new ResponseMatcher() {
void match(WebServiceMessage req, WebServiceMessage resp) {
EntityImportResponse response = marshaller.unmarshal(resp.payloadSource)
assert response.errorMessage.isEmpty()
assert response.isSuccess()
}
})
then: 'Entity is successfully imported'
noExceptionThrown()
}
Is there any way to add basic http auth to this client? I know how to add it to WebServiceTemplate but for this i have not found any way.
well, this question is actually a bad one, MockWebserviceClient doesn't deal with http at all, you need to set what you need in http requests outside of this client
Related
I have a spring boot application running with a graphql endpoint that validates and executes queries and mutations, however, I need to read one header in the incoming message in order to pass its value to another endpoint. Is there a way in graphql to read these values? some sort of getHeaders or something like that?
GraphQL itself does not define any things related to how to expose it over the network , so it does not define any things related to get HTTP header.It is up to developers to use their ways.So, it depends on the underlaying technologies you use to serve GraphQL over HTTP.
Consider you use graphql-spring-boot and graphql-java-tools , and assuming that you does not customize GraphQLContext , you can try to add DataFetchingEnvironment argument to your resolver function and then get the GraphQLContext from it. You can then get HttpServletRequest from the context and access the headers :
public Foo resolveFoo(Map<String,String> input , DataFetchingEnvironment env){
GraphQLContext context = env.getContext();
HttpServletRequest request = context.getHttpServletRequest().get();
request.getHeader("content-type");
}
The solution by #Ken Chan was not working for me. GraphQLContext had no method named getHttpServletRequest.
Solved it by using GraphQLServletContext instead. You can change the code to:
public Foo resolveFoo(Map<String,String> input , DataFetchingEnvironment env){
GraphQLServletContext context = env.getContext();
String header = context.getHttpServletRequest().getHeader("content-type");
}
Apparently the type of the context is not standardized. I use SPQR, and in my case I discovered (via debug):
DefaultGlobalContext<ServletWebRequest> context = handlerParameters.getDataFetchingEnvironment().getContext();
context.getNativeRequest().getHeader("something");
Not a direct answer to your problem statement, but one can use a Filter to handle it before the request hits the resolver endpoints (if that's a requirement):
public class HeaderFilter implements Filter {
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) {
final HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String headerVal= httpServletRequest.getHeader("<header string>");
try {
filterChain.doFilter(httpServletRequest, servletResponse);
} catch (IOException | ServletException e) {
//handle as you wish
}
}
These answers are too old, for latest versions. There are two ways (1) you can try to autowire one HttpServletRequest in your controller, such as
#Slf4j
#Controller
public class YourQueryController {
#Autowired
private HttpServletRequest request;
....
Then implement following logic to get header:
request.getHeader("Authorization")
(2) To make use of out-of-box support of RequestContextHolder over HTTP requests
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
val authorization = attributes.getRequest().getHeader("Authorization");
Google brought me this answer and unfortunately it was for Spring framework. Many use Spring framework but if you use Apache Tomcat with GraphQL integration like I do, you can do use this.
graphql.kickstart.servlet.context.DefaultGraphQLServletContext.DefaultGraphQLServletContext context = dataFetchingEnvironment.getContext();
jakarta.servlet.http.HttpServletRequest request = context.getHttpServletRequest();
String tokenBearer = request.getHeader("Authorization");
hth
I'm building REST services using spring-mvc and what I'm looking for now is a way to proxy HTTP request to external REST service from inside Spring MVC controller.
I'm getting HttpServletRequest object and want to proxy it making as few changes as possible. What is essential for me is keeping all the headers and attributes of incoming request as they are.
#RequestMapping('/gateway/**')
def proxy(HttpServletRequest httpRequest) {
...
}
I was trying simply to send another HTTP request to external resource using RestTemplate but I failed to find a way to copy REQUEST ATTRIBUTES (which is very important in my case).
Thanks in advance!
I wrote this ProxyController method in Kotlin to forward all incoming requests to remote service (defined by host and port) as follows:
#RequestMapping("/**")
fun proxy(requestEntity: RequestEntity<Any>, #RequestParam params: HashMap<String, String>): ResponseEntity<Any> {
val remoteService = URI.create("http://remote.service")
val uri = requestEntity.url.run {
URI(scheme, userInfo, remoteService.host, remoteService.port, path, query, fragment)
}
val forward = RequestEntity(
requestEntity.body, requestEntity.headers,
requestEntity.method, uri
)
return restTemplate.exchange(forward)
}
Note that the API of the remote service should be exactly same as this service.
You can use the spring rest template method exchange to proxy the request to a third party service.
#RequestMapping("/proxy")
#ResponseBody
public String proxy(#RequestBody String body, HttpMethod method, HttpServletRequest request, HttpServletResponse response) throws URISyntaxException {
URI thirdPartyApi = new URI("http", null, "http://example.co", 8081, request.getRequestURI(), request.getQueryString(), null);
ResponseEntity<String> resp =
restTemplate.exchange(thirdPartyApi, method, new HttpEntity<String>(body), String.class);
return resp.getBody();
}
What is the restTemplate.exchange() method for?
if you think of applying the API gateway pattern for microservices,
have a look at Netflix zuul which is a good alternative in the spring boot ecosystem. A good example is provided here.
I'm trying to build an api with Google Cloud Endpoints.
As Cloud Endpoints does not provide authentication beside Googles own OAuth I try to build my own. Therefore I want to access the parameters provided for the API (for example #Named("token") token) inside a servlet filter.
Unfortunately I cannot find any of the provided information inside the httpRequest. Is that normal? Is there a possibility to access the parameters?
I would appreciate if someone could help me!
UPDATE:
With the infos from jirungaray I tried to build an authentication using headers but ran into the same problem. Used a REST-Client to send some headers as I could not figure out how to do this with the API Explorer. Inside my filter I try to access the token from the headers:
#Override
public void doFilter(
ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String authToken = httpRequest.getHeader(Constants.AUTH_TOKEN);
...
chain.doFilter(request, response);
}
The reason why I try to do something like this, is that I'm using Guice for Dependency Injection and want my token to be injected inside another object.
With Guice I have the following Provider using the token to inject a FacebookClient (using the token) per request.
#Provides
public FacebookClient getFacebookClientProvider(#Named("fbToken") Provider<String> fbToken) {
return new DefaultFacebookClient(fbToken.get(), Version.VERSION_2_2);
}
As described in the Guice wiki (SevletModule) this uses a sevlet filter to get the information from the request.
Is there any solution to achieve this kind of DI with Cloud Endpoints?
Philip,
Yes, it does makes sense you are getting an empty request. Your endpoint calls are first handled by Google (they receive the API calls) and then those are processed and sent to a handler in your app. As this is all done in the background it's very easy to miss that your endpoints aren't actually getting the same request you sent, they get a completely different request sent from Google's infrastructure.
Even though your approach should work including tokens info in url makes them easier to sniff, even if you use SSL or encrypt your params the token is there in plain sight.
For what you are trying to achieve I recommend you include the token as a header in your request and retrieve that header by accessing the HTTPRequest directly on the endpoint, this is injected automatically if you include an HTTPServletRequest param in you endpoint method.
eg.
public APIResponse doSomething(SomeComplexRquestModel request,
HttpServletRequest rawRequest) {
}
If you still feel you should go with your original approach just comment and I'll help you debug the issue.
I've a set of APIs under /api. If my shiro.ini lists this as:
/api/** = authcBasic
Then basic auth is required. If anon is present in place of authcBasic then no auth is required. I'd like to be able to use the APIs with basic auth so I can e.g. programatically check the user is authenticated for POSTs and yet still allow anonymous access to GETs on the same URI. Alternatively to hide restricted data at the same URI for anonymous users and reveal it for auth'd users.
Is this possible?
You can roll your own custom shiro filter. Extend class BasicHttpAuthenticationFilter and override onPreHandle where you can check the servlet request method if it is GET or POST and act on it.
So something like:
public class MyFilter extends BasicHttpAuthenticationFilter {
#Override
protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) {
if ("GET".equals((HttpServletRequest)request).getMethod()){
return true;
}
return super.onPreHandle(request, response, mappedValue);
}
}
And in shiro.ini:
[main]
myfilter = mypackage.MyFilter
[urls]
/api/** = myfilter
Have you tried:
/api/** = authcBasic[permissive]
if user/password is set, shiro sends 401 if they are wrong
if user/password is not set, no 401. SecurityUtils.getSubject().authenticated is false
I think this works.
#Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
boolean loggedIn = false; //false by default or we wouldn't be in this method
if (isLoginAttempt(request, response)) {
loggedIn = executeLogin(request, response);
}
if (!loggedIn) {
// sendChallenge(request, response);
return true;
}
return loggedIn;
}
i.e. if authorisation details are provided execute login as normal (401 if auth details are invalid), else allow them in anyway (then check if authenticated, authorised later).
There's a caveat to this method though in that while it works with curl tests, using Apache's HttpClient Fluent API seems to send a request without authorisation and then send a second request with the credentials after a challenge response, which we're obviously now not sending. Arguably a bug in HttpClient but seeing as we've presumably deviated from the basic auth spec it's probably asking for it. So YMMV. This can be worked around by using preemptive auth and specifying the header value as suggested here.
I have a REST controller that has multiple GET/POST/PUT methods that all respond/request JSON.
I am not using Spring in this application (yet).
I was looking into the REST-assured framework and I like how that looks but I can only use it when my web server is up and running.
Is there a way for me to run a in-memory web server, or something like that?
Are there any examples of REST endpoint testing that someone can provide?
If you are using JAX-RS 2.0 you should find your answer here
You can take a look at the example also
An integration test example, could be:
public class CustomerRestServiceIT {
#Test
public void shouldCheckURIs() throws IOException {
URI uri = UriBuilder.fromUri("http://localhost/").port(8282).build();
// Create an HTTP server listening at port 8282
HttpServer server = HttpServer.create(new InetSocketAddress(uri.getPort()), 0);
// Create a handler wrapping the JAX-RS application
HttpHandler handler = RuntimeDelegate.getInstance().createEndpoint(new ApplicationConfig(), HttpHandler.class);
// Map JAX-RS handler to the server root
server.createContext(uri.getPath(), handler);
// Start the server
server.start();
Client client = ClientFactory.newClient();
// Valid URIs
assertEquals(200, client.target("http://localhost:8282/customer/agoncal").request().get().getStatus());
assertEquals(200, client.target("http://localhost:8282/customer/1234").request().get().getStatus());
assertEquals(200, client.target("http://localhost:8282/customer?zip=75012").request().get().getStatus());
assertEquals(200, client.target("http://localhost:8282/customer/search;firstname=John;surname=Smith").request().get().getStatus());
// Invalid URIs
assertEquals(404, client.target("http://localhost:8282/customer/AGONCAL").request().get().getStatus());
assertEquals(404, client.target("http://localhost:8282/customer/dummy/1234").request().get().getStatus());
// Stop HTTP server
server.stop(0);
}
}