I am trying to create an HttpClient that can validate an SSL certificate after every TLS handshake and before any other data is fetched/sent.
So the flow would look like this:
Create an HttpClient
Execute a request
The client connects to the host via HTTPS
After the TLS handshake was done, the client now knows the certificate
Pass the certificate to a callback. Execute actual request when callback succeeds, abort the request otherwise
In case the callback was successful, proceed as usual (e.g. pass the response etc.)
I was looking into SecurityContext already. The problem is that it only validates against a fixed set of certificates, but I want to validate the certificate dynamically based on the certificate that was sent by the host.
Also, I saw that there is a badCertificateCallback method in HttpClient, but this does not serve my usecase well as I want to validate every certificate, not just the invalid/bad ones.
I was wondering whether I could theoretically create a class that uses HttpClient as a superclass and therefore modify it's behaviour, but I am wondering whether there is a more elegant way that doesn't break that easily when the implementation of HttpClient changes.
Another idea of mine is to set a SecurityContext that rejects every single certificate by default. I could then use the badCerificateCallback to do the checks normally done by SecurityContext (check against a list of trusted certificates) and add my own validation on top of that. Is anyone aware of any drawbacks this might have? I got a little bit uncertain when reading about the limitations regarding iOS.
Has anyone here done similar things before and could give me a hint? :)
Thanks in advance!
For your usecase, it is better that you have your own version of BetterHttpClient.
However, instead of BetterHttpClient inheriting from HttpClient, you can use composition. Compose HttpClient inside BetterHttpClient. This will give you more control over what you want to use/update from the existing implementation and also this will be better guarded against any changes that HttpClient will go through
Related
I'm using signalr and since I wanna use websockets the [Authorize] attribute only authorize the client when the connection opens and then everything is ok. I would like the [Authorize] process to be triggered somehow.
Note: Must works using websockets
For example (I use Owin.Security.Cookies (UseCookieAuthentication)):
I connect to my application with a valid token in my cookie, once I've done this I manually remove the cookie in my browser and everything still works OK until I reload the page. Another example is if the client already has an open and valid connection, but the token limit expires - it's still valid until a reload is done.
Now to my question - Is there anyway I can force signalr to re-authorize the token every x min?
For the rest of this answer, I'm going to assume you're using SignalR hubs instead of PersistentConnections.
When you use SignalR's [Authorize] attribute or your own custom version of it, there are three methods to be aware of.
AuthorizeHubMethodInvocation
This is called, as you might expect, when a method on your hub is called. This could be any method, or only methods you apply an [Authorize] attribute to. You could put your code here.
AuthorizeHubConnection
This is probably what you want. Every time the client connects to the hub- which is a fairly frequent occurrence- this method is called. Do NOT confuse this with SignalR's Hub's idea of a connection. When a client is communicating with a SignalR hub, this method is called frequently- every method call or two on average.
This is where I would put the code you're talking about. You'll want to create a new attribute that inherits from SignalR.AuthorizeAttribute. In there, you'll want to override either AuthorizeHubConnection or AuthorizeHubMethodInvocation. Do note that if you don't override one of these methods, they will call UserAuthorized to make their decision.
In one of those two methods, you want them to return true if their cookie is valid (it exists, has a valid token, and hasn't expired), and false otherwise. This code will be called every time- or just about every time- a call is made to the hub, and deny access to the client if anything's wrong.
Hope this works!
I'm currently trying to figure out which options does retrofit offer to add an interceptor only to specific calls.
Background & use cases
I'm currently using retrofit 1.9
The use case is pretty simple. Imagine a user who needs to login and get a session token. There is a call.
/**
* Call the backend and request a session token
*/
#POST("auht_endpoint")
Observable<Session> login(...);
All other calls will require a token from the above session in the form of a request header. In other words, all subsequent calls will have a header which provides the session token to the backend.
My question
Is there a simple way of adding this header only to specific calls through interceptors?
What I've tried so far
Obviously the easiest approach was to add the #Header annotation to the specific calls and providing the token as a parameter
I guess one can inspect the url in the request inside the interceptor. Not very flexible.
Create different rest adapters with different interceptors. I heard you should avoid creating several instances of the rest adapter for performance reasons.
Additional info
I'm not committed to interceptors, I would use other solutions
I've said I'm using retrofit 1.9, but I'd be also interested in a way to do it with retrofit 2.x
Please note this is not an answer, comment box was too small.
I've recently had this problem and I came up to the same possible solutions as you.
First of all I put aside double adapters - thats a last resort.
#Header field seems ok, bacause you explicitly define that this specific request needs authorization. However it's kinda boring to use.
Url inspection in interceptor looks "ugly", but I've decided to go with that. I mean if all requests from a one specific endpoint need that authorization header then what's the problem?
I had two other ideas:
Somehow dynamically replace/modify okHttpClient which is used with Retrofit. After some tests I figured that it's not possible.
Maybe create some custom annotation #AddAuthorizationHeader to the call definition, which will do everything for you, but I guess it wouldn't be possible either.
And in this matter Retrofit 2.x doesn't bring anything new.
I've been recently investigating about Spring Integration and AMQP (RabbitMQ), as I need to communicate two applications (middleware and backend) with async approach, so that the middleware doesn't block when receiving client calls.
I first followed the simpler approach of implementing this in a synchronous, this meaning that I have a gateway interface and an outbound gateway (with requiresReply=true) on the middleware, and then an inbound gateway and a service activator on the backend. This initial approach works well (I've used Spring Integration XML config).
Now I need clarification on the approach to follow to make this work in an async way.
By looking at the RabbitMQ Tutorial 6, it's better to work with a callback queue and a correlationId, and per what I understood, this would be similar to calling Spring RabbitTemplate's convertAndSend() and then receive(), instead of convertSendAndReceive() (which would block until response is received).
I've checked the Spring Integration docs, where I need to replace the gateway interface on the middleware for it to return Future or ListenableFuture.
Async Gateway
Once that's done, I also looked at the documentation for the outbound gateway, where it says that it can work together with the RabbitTemplate to manage the correlationID and replyTo message attributes.
My questions are:
In order to make this work with an async approach, should I keep working with outbound/inbound gateways, instead of outbound/inbound message converters?
In case of following the outbound/inbound message converters approach (which sounds to me similar to what the RabbitMQ tutorial shows), how do I associate the Future on the gateway interface with the result coming back from with inbound channel adapter?
To be honest you don't provide an original business requirement. It might be a fact that there is really no reason to get deal with this async handsoff, because you have a #Gateway as an entry point which is thread-free and even if it is blocked to wait for the reply it doesn't impact other threads which may perform similar sendAndReceive operation. In most cases it is really just enough to do everything within the same requestor thread and don't loose performance with shifting to the shared ThreadPoolExecutor.
Right, the Future allows you to free a caller a bit to be ready to accept new requests within the same thread.
Since it is a MessagingGateway and you want to have a reply anyway, there is a hook associated with the request - TemporaryReplyChannel header. That's why that <outbound-gateway> works properly: it place its blocking reply to that channel for the gateway's return (or for FutureTask#set()).
I'd say that we can achieve the same TemporaryReplyChannel gain with that your async reply requirement.
You should use inbound/outbound channel adapter pair.
Before send the message to the <int-amqp:outbound-channel-adapter> you should do this <header-channels-to-string> for the <header-enricher>.
The server side maybe the same - <int-amqp:inbound-gateway>
You should use fixed replyQueue as a header for those message to send through the <int-amqp:outbound-channel-adapter>
the <int-amqp:inbound-channel-adapter> should be configured for that fixed replyQueue.
Both <int-amqp:outbound-channel-adapter> on client side and <int-amqp:inbound-gateway> must be configured for the mapped-request-headers="*" to allow to propagate that reply-channel header to the server and vise versa.
The <int-amqp:inbound-channel-adapter> on the client side will just send the reply to the reply-channel as it is for the <int-amqp:outbound-gateway>
You may need to take care about the correlationId manually, since <int-amqp:inbound-gateway> may require that to produce a reply properly.
Well, something like that...
HTH
Feel free to ask more questions. Or correct me if I misunderstood your question.
I'm looking into building an ASP.NET MVC application that exposes (other than the usual HTML pages) JSON and XML REST services, as well as Web Sockets.
In a perfect world, I would be able to use the same URLs for the Web Sockets interface as I do for the other services (and determine which data to return by what the user agent requests) but, knowing that IIS wasn't built for persistent connections, I need to know if there's a way that I can accept (and possibly even handshake) the Web Sockets connection and then pass the connection off to another service running on the server.
I do have a workaround in mind if this isn't possible that basically involves using ASP.NET to check for the Web Sockets connection upgrade headers, and responding with a HTTP/1.1 302 Found that points to a different host that has my Web Sockets service configured to directly listen to the appopriate endpoint(s).
If I completely understand your goal, I believe you can use the IIS7/7.5 Application Request Routing module to accomplish this.
Here's a quick reference: http://learn.iis.net/page.aspx/489/using-the-application-request-routing-module/
Rather than 302 responses you could use ISAPI_rewrite to direct to an appropriate endpoint (and manipulate the HTTP header to get it there)
http://www.isapirewrite.com/docs/
Otherwise no, IIS cannot natively pass off an HTTP connection. The current MSFT method is to use a 302 or something else that is intercepting the raw socket and performing header manipulation prior to sending to IIS (or whatever other application)
It strikes me that this would be a better question to ask Microsoft than to ask us. Web Sockets is new technology, and rather than looking for a hack, you might want to ask Microsoft how they plan to support it. IIS is their software. Poke around on http://iis.net (maybe in http://forums.iis.net) and see what you learn.
The way to do this is to use a unique Session ID that is associated with the Http Session. From the description, it seems like you might want to scope this to a single HttpApplication instance, but this is not necessary (you may also persist a session across many application instances). Anyway, this session ID needs to be attached somehow to each Http Request (either with a cookie, querystring, static variable with the HttpApplication instance, form data). Then you persist the identifying information about the Http session somewhere with the ID.
This identifying information may vary depending on your needs but could entail the entire http request or just some stripped down representation that serves your particular purpose.
Using this SessionID somewhere in the Http request allows you to restore whatever information you need to call and interact with the appropriate services. The instances of the services may also need to be scoped to the session as well.
Basically, what I am suggesting is that you NOT directly pass the Http connection to an external process, but instead pass the necessary data to the external process, and allow create a mechanism for sending callback data. I think looking into the mediator pattern may be helpful for you in understanding what I mean here. http://en.wikipedia.org/wiki/Mediator_pattern . I hope this helps.
I have a Flex application which is served via a JSP page. In this page I output the session ID using HttpSession when the page is loaded:
System.out.println("Session ID: " + session.getId());
In a very simple remote object hosted in BlazeDS (called from the flex application using an AMF Channel and standard RemoteObject functionality) I also output the session ID but this time using FlexSession (which as I understand is supposed to wrap around HttpSession).
System.out.println("FlexSession ID: " + FlexContext.getFlexSession().getId());
I would expect both IDs to be the same but this is not the case. The session IDs differ which is causing problems as there is data stored in the HttpSession which I need to be able to access from my remote objects within BlazeDS.
I've exhausted the reading material on BlazeDS and FlexClient/FlexSession/FlexContext but can't see why the FlexSession is not being linked to the HttpSession. Any pointers greatly appreciated.
I feel I must be missing something fundemental here, am I accessing the
I do not think that it is related to the FlashPlayer..is more related to the concept of FlexSession and how BlazeDS/LCDS works. For example you can have an active session even when not using the http channels - when using NIO/RTMP you are bypassing the application server and the http protocol. So it make sense to have an abstract class FlexSession with various implementations.
However when using BlazeDS FlexSession will wrap an HttpSession object internally, and removeAttribute/getAttribute/setAttribute are in fact calling the the same methods from the HttpSession object..so you can access all the data from the HttpSession. If not please provide more details.
However, it will not work when using RTMP channels(which exists only in LCDS by the way), you need to change your design in this case.
Thanks to both answers above I finally found the root cause and thought I'd share it on here.
The reason for differing session IDs was to do with the use of SSL for authentication and the use of AMF Channel rather than Secure AMF. Using the channel for the first time caused a new session to be created (hence the different ID) as the existing session related to the secure version of the site.
Silly configuration mistake but worth passing on - make sure that if using SSL that you're also using Secure AMF connecting to the secure endpoint rather than standard AMF or you'll run into the same session ID problems I faced.
Unfortunately this is just how the Flash player works. I have seen this same behavior many times.
The best solution I found was to establish the HTTP session and pass back the session ID. On the client side, you can then pass the session ID to the Flex application. You then send that ID from Flash to the server and use it to look up the existing session or establish a second session.
You will need to do something like this though, I have not been able to find a way to reliably get Flash to use the same session.