Sending Cookies over WCF using the ChannelFactory - cookies

I use an IOC container which provides me with IService.
In the case where IService is a WCF service it is provided by a channel factory
When IService lives on the same machine it is able to access the same cookies and so no problem however once a WCF Service is called it needs to be sent those cookies.
I've spent a lot of time trying to find a way to send cookies using a channel factory and the only way I could find that works is the following
var cookie = _authenticationClient.GetHttpCookie();
HttpRequestMessageProperty httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers.Add(HttpRequestHeader.Cookie, cookie.Name + "=" + cookie.Value);
using(var scope = new OperationContextScope((IClientChannel)_service))
{
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
var result = _service.Add(details);
if (result.Result == RPGResult.Success)
{
return RedirectToAction("Index", "Home", result.Id);
}
}
The problem with me using that method is that I have to know that I'm calling a WCF Service which is not always the case. I've tried writing a wrapper for the ChannelFactory that opens a new operationcontextscope when it creates a new service and various other solutions but nothing has worked.
Anyone have any experience with sending cookies over WCF Services?
I found a solution involving using SilverLight, unfortunately I'm not using silverlight, the solution is here: http://greenicicleblog.com/2009/10/27/using-the-silverlight-httpclient-in-wcf-and-still-passing-cookies/
Unfortunately standard .net doesn't contain the IHttpCookieContainerManager interface
Ideally I would be able to use something similar,i.e. I would be able to tell the channelfactory to pass a cookie whenever it opened.
If anyone has a better way to pass a token that is used for authentication that would be appreciated too.

I have a solution where I create a proxy class of IService and then every time a method on IService is called it invokes the proxy created by the channel factory but the call itself is wrapped in an operationcontextscope just like the one I have in my question.
I used the proxy factory from this link http://www.codeproject.com/KB/cs/dynamicproxy.aspx

Related

HttpContext.Current always null when sending request from unit test [duplicate]

This question already has answers here:
Mock HttpContext.Current in Test Init Method
(4 answers)
Closed 6 years ago.
I have Web Api controller Action method I am trying to unit test. I have one custom filter which runs before that action controller.
I have question regarding HttpContext.Current.User.Identity.Name that I am using inside my custom action filter.
It works nicely when I send my http post request from web client.
But, when I send http post request from my unit test than HttpContext.Current always complain for null
Don't understand where and what is wrong.
Anybody can please explain it?
Please note that I have seen answers at here but not sure where I need to add that code in my case.
Unit testing is not the same as calling your api through a web client.
When you are using a web client, you api is running in the context of you web server (IIS, for example) and the web server will provide the system with che "current" HttpContext.
If you call you code plain and simple from a unit test method you're not running in the context of a web server, but you're calling it simply as a method of a class. Obviously you can do it, but you need to "mock" (of fake, if you want) the current HttpContext to simulate you're running in a real web server.
Check this SO answer for the details on how to do it.
BTW, this is not the case when you run integration tests (means calling the real API throught a web client and just check the input-output results): in that case you are running your real code in a real context and everything will work fine.
HttpContext.Current is not set in a self hosted scenario like in your test.
You can however create a wrapper around HttpContext.Current and populate it before you run your test. Like this:
public static class CurrentHttpContext
{
public static Func<HttpContextBase> Instance = () => new HttpContextWrapper(HttpContext.Current);
}
And then somewhere in your test where you set up your HttpSelfHostServer, you populate the CurrentHttpContext.Instance. For example with FakeItEasy (https://github.com/FakeItEasy/FakeItEasy):
var context = A.Fake<HttpContextBase>();
CurrentHttpContext.Instance = () => context;
Then you can access CurrentHttpContext.Instance instead of HttpContext.Current in your filters:
public class MyAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
var context = CurrentHttpContext.Instance();
// stuff
}
}

How to secure restful webservice without using authentication

Can some one please let me know what are all the ways to secure restful web service written in spring boot project using spring rest(there is no user credentials check as this service is invoked by remote application sitting on different server)
Problem Statement:
I have a rest class and a method, which should be accessed by another remote application. Remote application will not send anything except body content and content-type. In this scenario how can I secure this rest service so that service can be accessible by only that particular remote application.
#RequestMapping("/rest")
#RestController
public class WorkflowController {
#RequestMapping(value = "ticket/create", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
#ResponseStatus(HttpStatus.CREATED)
#ResponseBody
public Long startWorkflow(#RequestBody TicketInfo ticketInfo) {
...//DO SOMETHING
Long id = 1L;
return id; // return some long value
}
}
Please suggest what is the way to achieve this.
Thanks in advance
Ok so i dont know if i completely understand your question, but ill asume different scenarios.
Say your client application sits on a
static ip you could create a filter and a whitelist of ip addresses, that would be really simple, and probably not good enough.
If thats not the case you can use a parameter either GET or POST and again create a filter, you'll have to send the authentication string in your first call to get authentication. you'll also have to implement the authentication manager.
if(hsr.getParameter("ex_code") != null){
String exCode= hsr.getParameter("ex_code");
String userToken = new String( Base64.getDecoder().decode(hsr.getParameter("ex_code")));
PreAuthenticatedAuthenticationToken token = new PreAuthenticatedAuthenticationToken(serviceThatReturnsAUserDetailsFacade.loadUserByUsername(userToken),
exCode);
token.setDetails(authenticationDetailsSource.buildDetails((HttpServletRequest) request));
try {
authentication = authenticationManager.authenticate(token);
....
If you do not want to implement any security & just would like to validate the host & port (only one app can run on a particular host & port) and assuming you using Spring then you can simply fetch following from incoming HttpServletRequest :-
a) RemoteAddr -> IP address of machine from which request originated.
b) RemoteHost -> Host name of machine from which request originated.
c) RemotePort -> Port of machine from which request originated.
Have one interfacing method in place which will validate this & if valid then allow it to go through while if invalid then return respective error msg to client.
Apart from this there is one other option also known as "Anonymous Authorization" with details here.

Grails: Create my datasource from a webservice

I've read a lot about switching between multiple datasource on runtime, but as far as I understand they're already defined datasources. I'm not quite sure on how can I just asign the datasources properties on runtime from a webservice call.
I don't need to switch between datasources, just need to create only one datasource with conection data coming from a webservice.
Is there a way to retrieve these parameters from the webservice and create the datasource from that?
The policy here is to retrieve the datasource parameters from a webservice for all the projects, that way the connection data is not inside a file nor into the code, and is only manipulated by DBAs from a global security aplication.
I tried to call the web service in the same datasource file, but it didn't work.
Info:
Web service is a Soap Web service
Grails: 1.3.9
Regards.
I think that you can create a BeanPostProcessor that take care of calling your webservice and changing the settings of your dataSource.
Probably you will need to delay the session factory creation, making sure Grails won't try to use your dataSource before you have all setted up correctly.
The BeanPostProcessor will looks like:
class WebserviceDataSourceBeanPostProcessor implements BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean
}
Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof DataSource){
def info = //call webservice here...
bean.username = info.username
bean.password = info.password
bean.url = info.url
//checkout more setters in: http://commons.apache.org/proper/commons-dbcp/apidocs/org/apache/commons/dbcp/BasicDataSource.html
}
return bean
}
}
And make sure you declared this Spring Bean in resources.groovy
beans = {
webserviceDataSourceBeanPostProcessor(WebserviceDataSourceBeanPostProcessor)
}
If you will have more than one project with this same config comming from a webservice you may think in the possibility of a plugin for this, reusing your code.

How to use Intersystem's session within web services

I am trying to set some session information in one web method and return it in another web method, but the session data is always empty on the second web method. Here is what I tried
Web Method 1 - Sets session information
Method StartSession() As %String [WebMethod]
{
set %session.NewSession = 1
set %session.Data("key") = "dude"
Quit "Session Started"
}
Web Method 2 - Gets session information should return dude, but is returning blank
Method TestSession() As %String [WebMethod]
{
Quit $Get(%session.Data("key"))
}
To use sessions with Cache web services you need to set the SOAPSESSION class parameter of your web service class equal to 1.
Doing so will cause the web service to return a SOAP session header in the response. If you are using a client that was built to expect this header you may not need to set up anything else. Otherwise, your client application will have to read this header and include it in all further requests, so the server can know which session you are using. An example of this header given in the documentation is:
<csp:CSPCHD xmlns:csp="http://www.intersystems.com/SOAPheaders">value of
CPSCHD token</csp:CSPCHD>
Note that security is a separate issue that your example doesn't address.
Also note that Intersystems has decided that web services will continue to use a license for some period of time after the call has been made. I can't find documentation on this, and I believe it's something like a few seconds per call. I believe that this can cause license issues that would not occur if you used other software to provide web services, and had that other software call Cache via some mechanism other than web services. I believe this is true even when that other software carefully follows all the rules in the license agreement about named and anonymous users. However, I'm not certain about any of this licensing stuff. Still, you might want to do some testing before you commit to an architecture.
As an alternative to psr's answer another way to handle state is to use custom SOAP headers.
For example:
Create a class for your custom SOAP headers like below:
Class Headers.TimeStamp Extends %SOAP.Header
{
Property TimeSent As %TimeStamp;
}
In the web method do this:
set h=##class(Headers.TimeStamp).%New()
set h.TimeSent=$ZTIMESTAMP
do ..HeadersOut.SetAt(h,"Timestamp")
This will generate the following SOAP header:
<SOAP-ENV:Header>
<TimeStamp xmlns:hdr="http://www.myapp.org">
<TimeSent>60712,70996.027Z</TimeSent>
</TimeStamp>
</SOAP-ENV:Header>
This will allow state to be maintained within the SOAP headers rather than using Cache's session management.

Session Variables and Web Services

I just wrote my first web service so lets make the assumption that my web service knowlege is non existant. I want to try to call a dbClass function from the web service. However I need some params that are in the session. Is there any way I can get these call these session variables from the webservice??
If you are using ASP.NET web services and you want to have a session environment maintained for you, you need to embellish your web service method with an attribute that indicates you require a session.
[WebMethod(EnableSession = true)]
public void MyWebService()
{
Foo foo;
Session["MyObjectName"] = new Foo();
foo = Session["MyObjectName"] as Foo;
}
Once you have done this, you may access session objects similar to aspx.
Metro.
You should avoid increasing the complexity of the service layer adding session variables. As someone previously pointed out, think of the web services as isolated methods that take all what is needed to perform the task from their argument list.
In general web services should not rely on session data. Think of them as ordinary methods: parameters go in and an answer comes out.
if you have to want Session["username"].ToString(); as in the other C# pages behind aspx then you should simply replace [WebMethod] above the WebService method with [WebMethod(EnableSession = true)]
thanks to :) Metro
Maybe this will work HttpContext.Current.Session["Name]
Or else you might have to take in some parameters or store them in a Database
Your question is a little vague, but I'll try my best to answer.
I'm assuming that your session variables exist on the server that is making the webservice call, and not on the server that hosts the webservice. In that case, you will need to pass the necessary values as parameters of your web service methods.
To use session in webservice we have to follow 2 steps-
Use [WebMethod(EnableSession = true)] attribute on the method.
Session["Name"] =50 (what ever you want to save)
Please check the following Example.
[WebMethod(EnableSession = true)]
public void saveName(string pname)
{
Session["Name"] = pname;
}