I'm new to web application in asp.net mvc 5. I'm curious about how static classes behaves in web application. I'd like to know how my program will behave.
Let's say I have CurrentUser static class which stores logged user id.
public static class CurrentUser{
public static int UserId {get; set;}
}
Which is set whenerever user is logging in.
My app is in external server.
So what will happen if:
User A log in -> userId is set to 1, then User B log in (they access to from differentlcoations) so user Id is set to 2. When User A would like to perform action which need to check his Id, will it be 1 or 2?
I checked one scenario where 2 differentpersons log in from one pc at the same time (different tabs) and I know that User Id will be 2 for both of them (when User B logged in as second to the app). How to resolve this?
I've already read: Static classes in web applications.
I know that my solution may be error prone because every one has access to that class but I don't know if static classes in web app aren't store per user (thread?)?
If you store current user in session storage it will be better than static class. Because there is one copy of static class and fields and for every user login the last login is kept.
Related
I am currently working on multitenant saas webapp using aspboilerplate and would like to implement the permission management but I got little bit of confusion.
Firstly, what's the difference between MultitenancySides.Host and MultitenancySides.Tenant which I have found here....
public override void SetPermissions(IPermissionDefinitionContext context)
{
context.CreatePermission(PermissionNames.Pages_Users, L("Users"));
context.CreatePermission(PermissionNames.Pages_Roles, L("Roles"));
context.CreatePermission(PermissionNames.Pages_Tenants, L("Tenants"), multiTenancySides: MultiTenancySides.Host);
context.CreatePermission(PermissionNames.Pages_Events, L("Events"), multiTenancySides: MultiTenancySides.Tenant);
}
Secondly, how [AbpAuthorize] differs to
[AbpAuthorize(PermissionNames.Pages_Tenants)]
I found those in event service ( first link and second link) ,
[AbpAuthorize]
public class EventAppService : EventCloudAppServiceBase, IEventAppService
{
private readonly IEventManager _eventManager;
private readonly IRepository<Event, Guid> _eventRepository;
and in TenantService
[AbpAuthorize(PermissionNames.Pages_Tenants)]
public class TenantAppService : AsyncCrudAppService<Tenant, TenantDto, int, PagedResultRequestDto, CreateTenantDto, TenantDto>, ITenantAppService
{
private readonly TenantManager _tenantManager;
Here is what I want and expect to implement permissions in my Multitenant Saas (Core + Angualr SPA) ...
There will be different features ( I say modules) including Event (CRUD), Library(CRUD), Exam(CRUD), Result(CRUD), Attendance(CRUD) and I would like to have full access (CRUD) permission to tenant superadmin (by default assigned when tenant is created) and then superadmin can create role (Assigned module and permission (CRUD) to specific module).
To make it simple, if system has Attendance module/feature then by default a tenant's Superadmin will have full CRUD access whereas if Staff role is created and restricted to CR but not allowed to UD.
I have gone through this tutorial but unable to sort it out.
Thank you.
Firstly, what's the difference between MultiTenancySides.Host and MultitenancySides.Tenant?
MultiTenancySides.Host → can only be assigned to Host users (user.TenantId == null).
MultiTenancySides.Tenant → can only be assigned to Tenant users (user.TenantId != null).
Secondly, how [AbpAuthorize] differs from [AbpAuthorize(PermissionNames.Pages_Tenants)]?
[AbpAuthorize] → user is logged in.
[AbpAuthorize(PermissionNames.Pages_Tenants)] → user is logged in and has that permission.
Background
I've created a working bot in C# but I'm failing to expand it to be a multi-tenant bot. I have created multiple bots in the Microsoft portal using this technique to identify themselves from the messaging endpoint:
https://example.com/api/messages/bot1
https://example.com/api/messages/bot2
https://example.com/api/messages/bot3
I can grab the LastSegment from the URL while in the MessagesController and store it in PrivateConversationData so I know which bot is talking in the current conversation. I intended use this stored 'bot id' in order to retrieve the Microsoft AppId & Password from the web.config (the bot's credentials are stored as a series of custom entries and not the standard appSettings as that only works for a single bot).
Credentials Problem
The authentication works well (nearly) as described here except when using async code with .ConfigureAwait(false) I can't get the HttpContext.Current as it becomes null when running on a different thread. This means I can't get the authenticated user's credentials either by looking them up in the web.config or by calling GetCredentialsFromClaims() since I've lost the authenticated user. If I use .ConfigureAwait(true) I just get deadlocks all over the place.
I have the credentials in the web.config but they are stored per bot and I need the 'bot id' from the URL above in order to get the credentials.
Question
The crux of the problem is: I need the URL to get the 'bot id' and I need the 'bot id' to get the credentials from the web.config but I can never reliably get access to the URL once I've passed a .ConfigureAwait(false) in the code. On the flip side, I can't get the 'bot id' from the PrivateConversationData since I need the bot's credentials in order to load it. A bit chicken and egg :-(
If anyone has any ideas of what I may be doing wrong or has an alternative approach to know which 'bot id' is currently executing I'd very much appreciate it.
Thanks
Please find below given the sample code.
public class StartUp {
public void Configuration(IAppBuilder app) {
var builder = new ContainerBuilder();
//Note: Initialize / register the Metadata Service that can bring the tenant details from the corresponding store
builder.RegisterType<TenantMetadataService>().As<ITenantMetadataService>();
//Note: This helps you in accessing the TenantMetadata from any constructor going forward after the below registry
builder.Register(ti => TenantMetadata.GetTenantMetadataFromRequest()).InstancePerRequest();
//TODO: Register the various services / controllers etc which may require the tenant details here
}
}
public class TenantMetadata {
public Guid TenantId { get;set; }
public Uri TenantUrl { get;set; }
public string TenantName { get;set; }
public static TenantMetadata GetTenantMetadataFromRequest() {
var context = HttpContext.Current;
//TODO: If you have any header like TenantId coming from the request, you can read and use it
var tenantIdFromRequestHeader = "";
//TODO: There will be a lazy cache that keeps building the data as new tenant's login or use the application
if(TenantCache.Contains(...))return TenantCache[Key];
//TODO: Do a look-up from the above step and then construct the metadata
var tenantMetadata = metadataSvc.GetTenantMetadata(...);
//TODO: If the data match does not happen from the Step2, build the cache and then return the value.
TenantCache.Add(key,tenantMetadata);
return tenantMetadata;
}
}
Note
The above code snippet uses the various service placeholders, cache and the other methods which will require to be used based on the designed application services. If you wish not to cache the tenant metadata, if it may contain some sensitive data, you can remove the caching implementation parts.
This implementation can be spread across all your web facing portals like your Web UI, Web Api and WebJobs etc so that it is same across all apps and it is easy to test and consume.
HTH.
I am creating a login system and I want a way to sort of cache information without retrieving the same information from the database.
for example I would have a static class called tokenData. token data would be a private class to store login token, username, expireDate, etc. So every time I visit another page it would check the static class for the data. The token is then stored in session / cookie to produce the lookup. If the data is not in the token static class (e.g. application pool restart) then it would check the database for the record when the user logs in and creates another based on the data in the token table.
Can someone offer me any advice is this is acceptable practice or offer me anything to improve and issues that can arise?
an exmaple is
public class userToken
{
private string name;
private string tokenId;
private static List<userToken> userData = new List<userToken>();
public void add(userToken);
public userToken Find(string tokenId);
}
Never ever ever use static for user or session specific data. static is shared across ALL sessions! You might end up with user sessions sharing confidential data.
Use HttpContext.Session or HttpContext.Cache.
Your solution can introduce errors when run on more than a single server with a single user. The cache you are building is not thread safe. It will also introduce errors when your app is run across 2+ servers in a cluster (load balanced).
I would look into using a proper caching toolset (memcached, etc.)
I am creating an application where I first login with my user account. This user account could be windows or self managed account in my own application database.
Now I want to authorize the logged in user before accessing any business objects of my application. Objects are mapped with database tables so eventually I want to authorize user first, whether to give data back to user or not.
After logging in I store user credentials globally as an object of UserCredential class. But I don't want to pass this credentials to each object when I am creating it.
Is there any way to check/reach the application context (including UserCredential object I stored globally) for each business objects automatically which I am creating further?
I want to achieve this in C#. Code example is much appreciated.
You should take a look at the PrincipalPermissionAttribute class, here is the MSDN documentation:
PrincipalPermissionAttribute class MSDN documentation
The PrincipalPermissionAttribute throws a SecurityException when the Thread.CurrentPrincipal does not match the security assertion.
Examples:
User's name is GDroid:
[PrincipalPermission(SecurityAction.Demand, Name = "GDroid")]
public void YourBusinessMethod()
{
// Do something
}
User belongs to Admin role:
[PrincipalPermission(SecurityAction.Demand, Role = "Admin")]
public void YourBusinessMethod()
{
// Do something
}
User is authenticated:
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public void YourBusinessMethod()
{
// Do something
}
I am working in a DocumentManagement System. The users defined in the database can create/manipulate his own documents based on their access rights defined. The owner of a document can let other user access/modify the document (stored as XML Contetnt). I need to autorize the LoggedIn User Whenever a document is opened for editing. The document has alredy a CreatedBy,EditingUser properties.
There is chance that a document owned by User "A" can be edited by user "B" if he has the Write Access for that document. Now I need to check the authorization of the LoggedIn user for the document which is opened for editing (inside the Save() BL method of the DocumentManager object). Here I need to access the LoggedIn User details inside the BL method which is filled after Login process (which should not be changed after that).
My application is WPF application. So what is the best approach to handle the situation like this. I need to often check the rightst of the Loggedin user aganist the Document in my application (particularly inside the BL methods).
I would rather suggest a decouple mechanism to authorize users. So the actual application need not to worry about the authorization.
You can define the authorization logic a policy - XACML.
XACML is the de-facto standard for authorization.
Once you have the authorization logic defined in XACML PDP - before executing the user actions, your application will call the XACML PDP - and ask whether the logged in user is eligible to perform this action against the given resource.
Using XACML will give you flexibility to change the logic of authorization, with out even touching the application logic.
Also - you can define very fine-grained rules with XACML.
You need to take session approach. You need to maintain a static class as below. When ever user is logged in, you need to add them to the list on BLL
public static class Session{
public static Dictionary<User, DateTime> loggedInUser;
public static Add(User user){
loggedInUser.Add(user, DateTime.Now);
// raise event user arrival
}
public static GetUser(int Id){
// fetch user;
}
public static Remove(User user){
loggedInUser.Removed(user);
// raise event user left
}
// TODO: add timer to check itself. If not activity done in past n minutes,
//log him out
}