I have an application with a server "AppDomain", which accepts calls from separate AppDomains (which host plugins, developed by other people and not trustworthy).
From the server AppDomain, I need to know which "Plugin" (AppDomain) is actually making the call, so that I can ensure that this plugin has access to the resource.
I could just pass in the credentials to the remoting method call, but I am concerned that in doing so that a crafty programmer of "Plugin A" may change the code so that it appears to be coming from "Plugin B".
I have looked into creating my own "ObjRef" implementation on the Server app, thinking that "ChannelInfo.ChannelData" may hold information on the client plugin making the call, and implemented the following code:
public int DomainId
{
get
{
int domainId = -1;
// The type "System.Runtime.Remoting.Channels.CrossAppDomainData" is not Public,
// so we have to use reflection to get access to it.
for (int i = 0; i < ChannelInfo.ChannelData.Length; i++)
{
object o = ChannelInfo.ChannelData[i];
if (o.ToString() == "System.Runtime.Remoting.Channels.CrossAppDomainData")
{
System.Reflection.BindingFlags flags =
System.Reflection.BindingFlags.GetProperty
| System.Reflection.BindingFlags.Instance
| System.Reflection.BindingFlags.NonPublic;
domainId = (int)o.GetType().GetProperty("DomainID", flags).GetValue(o, null);
}
}
return domainId;
}
}
But the DomainId retrieved by this is the same as the Servers AppDomain.CurrentDomain.Id, when I really want the Client (caller) AppDomain Id
It feels like this is too hard :-)
Any ideas?
Can you ask them to put some sort of ticket in the call context?
If you can, It would be easy to identify the caller and act in consequence.
Maybe it's not the best solution but should work. We did it ones and I think it's still in prod ;)
Related
Can I write something like the following (in an assembly being used in an ASP.NET web page)?
public static string CurrentAuthenticatedUserFromHttpRequest
{
get
{
if (HttpContext.Current.Items["AuthUser"] == null)
{
return string.Empty;
}
return HttpContext.Current.Items["AuthUser"].ToString(); //set in "TryAuthenticate"
}
}
It is going to be a static read-only property. The value (to HttpContext.Current.Items["AuthUser"]) is set through a httphandler.
Just wondering on how this would perform during multiple requests. Is the data going to be accurate when multiple users try to access the same property (in multiple requests), even when high volumes of requests come in?
Yes, this is threadsafe. The static HttpContext.Current property differs per thread and contains the context for the request that the thread is currently handling.
As with many real world applications out there, the security (login/password) was just there to grant/deny access to the complete application. Now the client has asked for fine grained security like some web pages should only be viewable, some users can delete other cannot etc.
basically the client is requesting the following.
Effective Permission:: Users--> Web page --> Type of Access (View,Create/Edit,Delete)
Details of Application
ASP.NET/C#
MSSQL Server 2008 for Biz data
SQLCE for users/passwords/profiles/logs
Ext.NET for main UI
We discussed that it is better to enhance the security.sdf file and have a table for screens (webpages) and a join table of user + screens + a number that denotes type of access i.e.
1: Read
2: Write
4: Delete
These can be checked using bitwise operator. The application uses ASP.NET impersonation to gain access to MSSQL2008
The problem is how to implement it in the web application?
If anyone has better ideas please share!!!
You can use the IsInRole function and categorize your users into roles. Each role can have some action that can be done only. So by asking in witch role is the user you can let him do or not thinks.
HttpContext.Current.User.IsInRole("Role")
Or you can do it reversely, ask if this action is available for this role, here is a simple object, with permissions and checks.
public enum csPermissions
{
pActionDelete = 1,
pActionEdit = 2 ,
// more names...
}
private int[] AdminPermission = {
(int)csPermissions.pActionEdit,
(int)csPermissions.pActionDelete,
// more permissions...
};
private int[] BackOfficePermission = {
(int)csPermissions.pActionEdit,
// more permissions...
};
public static bool IsThisAllowed(csPermissions AskPermitForThisAction)
{
// questions here for all users roles...
// here is only an example
if (HttpContext.Current.User.IsInRole("Administator")))
{
for (int i = 0; i < AdminPermission.Length; i++)
if (AdminPermission[i] == (int)AskPermitForThisAction)
return true;
}
// no permission found
return false;
}
I have a website written in ASP.NET.
I would like to add subdomains of states. such as nevada.mysite.com.
However, I'd like my whole site to be custom made for that subdomain.
That is, I'd like to capture in each page which subdomain context I am and show different things.
I do not want to seperate to different websites. I want them all to reside in the same website in the IIS
what is the best and proper way of handling such issue?
where do you suggest to hold and save the global variable of the state?
Thanks!
First, have all of your subdomains point to a single IP address in DNS.
Next, configure IIS to listen for all connections on that IP (don't specify a host name)
Then write an HttpModule (or perhaps use Global.asax) with a handler for the BeginRequest event. Extract the subdomain name from the incoming URL, and store it in HttpContext.Items["state"] (the Items Dictionary is unique per request).
This is a great question. I've done this before except I didn't use sub domains, I used different URL's, but they still used the same code and database. I wanted a way to integrate this a bit more tightly with my LINQ to SQL code without having to type in where clauses on each one. Here's what I did:
public static IEnumerable<T> GetDataByDomain<T>(
IQueryable<T> src) where T:IDbColumn
{
//1 == website1
//2 == website2
//3 == both
string url = HttpContext.Current.Request.Url.Host;
int i = url == "localhost"
|| url == "website1.com"
|| url == "www.website1.com" ? 1 : 2;
return src.Where(x => x.domainID == i|| x.domainID == 3);
}
Basically when querying a table with LINQ to SQL I have my own custom where clause.
Used like so:
using (var db = new MyDataContext())
{
var items = Utility.GetDataByDomain(db.GetTable<Item>()).Where(x => x.isVisible);
}
Finally in each table where I had data that needed to be specified for one web site or both I added a column that took a value of 1,2 or 3(both). Additionally in my LINQ data context I made a partial class and referenced my interface:
public partial class Item : Utility.IDbColumn
{
}
The reason we need the following interface is because the first method takes an unknown type so obviously I can't select a property from an unknown type unless I tell it that any type I pass to it relies on an interface which contains that property.
Interface:
public interface IDbColumn
{
int domainID { get; set; }
}
It's kind of an interesting system, probably could have done it in many different ways. Built it a while ago and it works great.
I can't seem to find a solid answer anywhere. I THINK i found one with respect to JMS but it was confusing.
It really depends what stack of j2EE are you using? Is it just web, ejb layer or both?. If we are talking about the web then you can use asynchronous servlet introduced in the newest Java EE specification, if you are using plain EJB's then the natural choice would be Messege driven beans (mentioned JMS). You can of course design a custom solution where for example you send some data to process and then the j2ee application itself calls your application (with http request for example) to notify that its done running the job. Possibilities are endless and if one is better than other always depends on the specific scenario.
If I understand correctly what you are talking about is the ability to start a task (that will take some time) then respond to the user while that task is still doing it's stuff. Depending on your requirements it is really quite simple and you can use a plain old Java Thread to perform the operation.
public class DoSillyCounting extends Thread {
private volatile int counter;
public int getCounter() { return counter; }
public run() {
while (counter < 10) {
counter ++;
try { Thread.sleep(1000); }
catch (InterruptedException ie) { }
}
}
}
In your setup page you might do this: (session is an HttpSession)
DoSillyCounting doSillyCounting = new DoSillyCounting();
doSillyCounting.start();
session.putValue("tenSecondsCounter", doSillyCounting);
/* Here you can respond to the user while the Thread is executing */
And in your status page you might do this:
DoSillyCounting doSillyCounting =
(DoSillyCounting)session.getValue("tenSecondsCounter");
out.print(Integer.toString(doSillyCounting.getCounter());
if (doSillyCounting.isAlive()) {
out.print("Still Working on it");
} else {
out.print("Yippee, I finished");
}
Of course, this is a rather useless example and this model is not a good idea when you may have a large number of requests to satisfy, it would then be worth looking at a ThreadPool implementation or using something like JMS.
I have an ASP.NET application with a lot of dynamic content. The content is the same for all users belonging to a particular client. To reduce the number of database hits required per request, I decided to cache client-level data. I created a static class ("ClientCache") to hold the data.
The most-often used method of the class is by far "GetClientData", which brings back a ClientData object containing all stored data for a particular client. ClientData is loaded lazily, though: if the requested client data is already cached, the caller gets the cached data; otherwise, the data is fetched, added to the cache and then returned to the caller.
Eventually I started getting intermittent crashes in the the GetClientData method on the line where the ClientData object is added to the cache. Here's the method body:
public static ClientData GetClientData(Guid fk_client)
{
if (_clients == null)
_clients = new Dictionary<Guid, ClientData>();
ClientData client;
if (_clients.ContainsKey(fk_client))
{
client = _clients[fk_client];
}
else
{
client = new ClientData(fk_client);
_clients.Add(fk_client, client);
}
return client;
}
The exception text is always something like "An object with the same key already exists."
Of course, I tried to write the code so that it just wasn't possible to add a client to the cache if it already existed.
At this point, I'm suspecting that I've got a race condition and the method is being executed twice concurrently, which could explain how the code would crash. What I'm confused about, though, is how the method could be executed twice concurrently at all. As far as I know, any ASP.NET application only ever fields one request at a time (that's why we can use HttpContext.Current).
So, is this bug likely a race condition that will require putting locks in critical sections? Or am I missing a more obvious bug?
If an ASP.NET application only handles one request at a time all ASP.NET sites would be in serious trouble. ASP.NET can process dozens at a time (typically 25 per CPU core).
You should use ASP.NET Cache instead of using your own dictionary to store your object. Operations on the cache are thread-safe.
Note you need to be sure that read operation on the object you store in the cache are threadsafe, unfortunately most .NET class simply state the instance members aren't thread-safe without trying to point any that may be.
Edit:
A comment to this answer states:-
Only atomic operations on the cache are thread safe. If you do something like check
if a key exists and then add it, that is NOT thread safe and can cause the item to
overwritten.
Its worth pointing out that if we feel we need to make such an operation atomic then the cache is probably not the right place for the resource.
I have quite a bit of code that does exactly as the comment describes. However the resource being stored will be the same in both places. Hence if an existing item on rare occasions gets overwritten the only the cost is that one thread unnecessarily generated a resource. The cost of this rare event is much less than the cost of trying to make the operation atomic every time an attempt to access it is made.
This is very easy to fix:
private _clientsLock = new Object();
public static ClientData GetClientData(Guid fk_client)
{
if (_clients == null)
lock (_clientsLock)
// Check again because another thread could have created a new
// dictionary in-between the lock and this check
if (_clients == null)
_clients = new Dictionary<Guid, ClientData>();
if (_clients.ContainsKey(fk_client))
// Don't need a lock here UNLESS there are also deletes. If there are
// deletes, then a lock like the one below (in the else) is necessary
return _clients[fk_client];
else
{
ClientData client = new ClientData(fk_client);
lock (_clientsLock)
// Again, check again because another thread could have added this
// this ClientData between the last ContainsKey check and this add
if (!clients.ContainsKey(fk_client))
_clients.Add(fk_client, client);
return client;
}
}
Keep in mind that whenever you mess with static classes, you have the potential for thread synchronization problems. If there's a static class-level list of some kind (in this case, _clients, the Dictionary object), there's DEFINITELY going to be thread synchronization issues to deal with.
Your code really does assume only one thread is in the function at a time.
This just simply won't be true in ASP.NET
If you insist on doing it this way, use a static semaphore to lock the area around this class.
you need thread safe & minimize lock.
see Double-checked locking (http://en.wikipedia.org/wiki/Double-checked_locking)
write simply with TryGetValue.
public static object lockClientsSingleton = new object();
public static ClientData GetClientData(Guid fk_client)
{
if (_clients == null) {
lock( lockClientsSingleton ) {
if( _clients==null ) {
_clients = new Dictionary``();
}
}
}
ClientData client;
if( !_clients.TryGetValue( fk_client, out client ) )
{
lock(_clients)
{
if( !_clients.TryGetValue( fk_client, out client ) )
{
client = new ClientData(fk_client)
_clients.Add( fk_client, client );
}
}
}
return client;
}