We have an application that allows users to see a list of documents.
Depending on the role of the user and the properties of the document, we want to filter out some of the documents on the list. For example we want to allow the user to view a list with only the documents that he created and a grey out line for the rest.
At the moment the application executes an SQL SELECT command which returns a list of entries that the user can and cannot see. We want afterwards to restrict this resultset according to the user's permissions and roles.
Our questions are the following:
Can this be done via Shiro?
What is the proper way to place such restrictions when using Shiro? e.g. shall we restrict the list from the start, using the SELECT statement ?
You have a few options:
First since it sounds like you want to display the full list of documents to the user you will still need to query all of them. (though I caution you on this, as that leaks information the user does NOT have access too. For example of user 'jcoder' sees a document titled 'Super Secret Passwords', he knows you have this document. That may or may not matter for your use cases)
If your use case is ONLY "only authors can edit their own documents" then you could just simple username comparison (which I'm guessing you are doing now)
Most use cases are NOT this simple, and require the author as well as administrators, tech writers, etc. access to the resource. So you could assign a set of permissions to the resource. We can call it publications:docs:<document_id>:<action>, or just docs:<document_id>:<action>. Where the document_id is some unique document identifier, and action what is being done to the resource (in a typical CRUD app they would be create, read, update, delete).
This permissions can be granted to any user and publications:docs:<document_id>:* could be granted to the author. This also allows permissions to be revoked if someone changes position or the document needs to be marked read-only too all users except administrators.
The snippet of code would look something like:
if(SecurityUtils.getSubject().isPermitted("publications:docs:":"+ documentId + ":read" ) {
// do something
}
Or you can check them them all at once.
Your application would need to keep track adding permissions to users.
Take a look at: http://shiro.apache.org/permissions.html
And a similar question: Java – efficient, database-aware instance-level authorization?
Related
In my app, each user has a document in the users collection of my database. Under each user's document, there is a subcollection for that user's uploaded foods. By default, I want to limit it so that the user cannot add more than 25 foods to their personal subcollection. Is there a way to check via Security Rules if the collection size is <= 25?
It's not possible in security rules. It's not even possible with a regular client query.
If you want a document count, you will have to manage one of your own in a single document. Then you could write rules to check against the count that you manage in that document.
I try this:
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/sonoo","root","password");
but it's very easy for someone to hack strings of username and password.
Opening Application with zip, winrar or any else program look like this and read code.
How can I secure my connection?
You need to decide what permissions someone who gets a copy of your JAR has. Do they have permission to run database queries or not?
If they should not: delete the database connection. They don't have permission.
If they should: then they can have the password. They have permission.
What seems to be tripping you up is that you are giving out the root password for your database, and so you want the the third option: "They should be able to do some database queries, but not others."
The JAR file is the wrong place to try to solve that problem. If you try to solve this at the JAR file level, one of two things will happen. Either your users were trustworthy all along and you wasted your time with whatever elaborate scheme you used, or some of your end-users are untrustworthy and one of them will hack you. They will hack you by stepping it through the JVM and editing your query strings right before the JVM sends them out, at the very last second, if they absolutely have to. Everything you do at this level will be security theater, like getting frisked at the airport, it doesn't make you significantly safer but there is a tiny chance that you can say "but we encrypted it!" and your clients might not dump you after the inevitable security breach.
That problem needs to be solved within the database, by creating a user account which does not have the permissions that they should not have. When you do SHOW GRANTS FOR enduser#'%' it will show you only the sorts of queries that they are allowed to do.
In many cases you want to give the user account a more fine-grained permission than just INSERT, SELECT, or UPDATE on a table. For example, you might have the logic "you can add to this table, but only if you also update the numbers in this other table." For these, you should use stored procedures, which can have their permissions set to either "definer" or "invoker": define it by a user with the appropriate permissions and then the invoker gets to have advanced permissions to do this particular query.
In some cases you have a nasty situation where you want to distribute the same application to two different clients, but they would both benefit significantly (at the expense of the other!) from being able to read each other's data. For example you might be an order processor dealing with two rival companies; either one would love to see the order history of the other one. For these cases you have a few options:
Move even SELECT statements into stored procedures. A stored procedure can call user() which can still give you the logged-in user, even though they are not the definer.
Move the database queries out of the shared JAR. Like #g-lulu says above, you can create a web API which you lock down really well, or something like that.
Duplicate the database, move the authentication parameters to a separate file which you read on startup.
Option 3 requires you to write tooling to maintain multiple databases as perfect duplicates of each other's structure, which sucks. However it has the nice benefit over (1) and (2) that a shared database inevitably leaks some information -- for example an auto_increment ID column could leak how many orders are being created globally and there might be ways to determine something like, "oh, they send all of their orders through this unusual table access, so that will also bump this ID at the same time, so I just need to check to see if both IDs are bumped and that'll reveal an order for our rival company".
You can create a webservice in PHP (or java or others). This webservice is stocked on a server and he's contain access and query to your database.
With your desktop app, just send a request (POST, GET) to your web service.
Exemple in PHP webservice :
if (isset($_POST['getMember'])){
do a query in your database
insert result into JSON
return JSON
}
I just want to double check to make sure that a user is allowed to be at page.
Previously I have been pulling the userName out of the session and seeing if that value is null. This is fine, but I was just wondering if isNew() would have the same results or if there might be some reason that a user could have a forged or previous session.
From reading about the method I feel like it would work just fine to use this way, but want to make sure I am not missing something.
I am doing this validation in the back with Java. The front end will be doing it's own validation too, using JS I imagine, it's more just an extra check I guess.
Thanks!
In reading a few books such as PHP Hacks and Web Site cookbook, and MySQL, their common strategy is that every single page that can be accessed by a client should check for a valid session ID, a server event sequence ID, the users site status and the users role.
The site status (in SQL server) is usually: 'is_owner', 'is_creator', 'is_admin', 'is_member', 'is_new', 'is_suspended', 'is_banned'.
The entries for 'Role' is simular but pertains to a members role.
If a member comes out of suspension they may get back their status and role.
Roles can be: 'is_owner', 'is_creator', 'is_supervisor', 'is_manager', 'is_boss', 'is worker', etc.
Each page checks these 4 categories against the database to make sure the packet was not hijacked, or a sudden rise in rank, or they are a member again when they had been banned.This does not include other fields such as permission to view or join chat or a group, but if that page offers that option it needs to confirm it with the database first.
The steps to accessing a page may involve several pages of query before the client is granted access. Checking one item to grant access to all is asking for trouble.
I need some of your inputs in deciding a right approach in following case.
I am currently working on a ecommerce application ( An online shopping website).
Here, on homepage of application, I have to display a list of products available in shop.
The end user has a facility of applying a filter to products list so that only the products satisfying the applied filter will be displayed.( Filter like display products with selected company,price range and so on ).
So, my question is regarding the logic for applying the filter.
I have following ideas in mind to implement this requirement.
As user selects different criterias on page, generate SQL query dynamically( By appending a string with required where clauses) and fire the generated SQL on each request.
Set up all possible combinations of SQLs in database already ( say in a stored procedure ). As user changes the criteria, select the appropriate SQL in stored procedure to run.
Can anyone please guide me, if there is any better way to handle this requirement ?
Any input is highly appreaciated.
Please let me know if more information is required in this context.
Thanks.
I would do the first one, but you've got to be wary of SQL injection attacks.
I don't like your second option because stored procedures are usually written in a language that I consider worse than java. That's pure opinion, but that's my opinion. They also aren't database agnostic.
Alternatively, you can use JPA for this. For example, there are Hibernate Filters.
Something that works well for sites like yours is to not change the query to retrieve different items to offer for sale but, instead, to offer the all the same items but to change the order they appear on the site.
So, if the user wants items priced $100-$500, you still show the items under $100 and over $500 but the ones in that range appear first, then the ones outside the range in some sort of random order. Or, if there are multiple criteria, you may show items meeting all but one of the criteria.
This also solves the problem of the user asking for coffee mugs over $500. If there are no matches, you don't give the user 0 items to select from but you give them some of the other items with preference to coffee mugs of any price. Presenting the user with no items to purchase is a lost chance that they might see something they want.
You can implement this in either of the ways you mentioned except you are varying the "order by" clause.
My personal preference is to NOT use stored procedures.
But, if you are working with a large group with experts in database use in the group that can optimize the database usage and keep the stored procedures in top shape, that might be an option.
If its a single person or small team of java developers, don't expect them to be experts in Java and SQL/Database as well. Play to your teams strengths.
I am working currently on a web project where users can create image galleries and upload pictures. Optionally they can mark pictures as private so that nobody else can look at them.
Now i am not sure how to properly implement the protection mechanism. Of course i have some ideas but none of them seems to be optimal.
Here is one of my ideas:
Create a table for user images:
image_key (PK) | user_id | public_image (boolean)
the picture will be saved on the harddisk using the iamge_key and can be accessed via http by an url looking like this:
http://www.myCompany.com/images/image_key
a servlet will be mapped to the url path images, the key will be extracted, a stream to the file on the harddisk will be openend and the picutre will be streamed.
additionally there will be a reverse proxy in front of the servlet container to provide some caching.
The issue with this solution is that my serlvet would have to go to the database and check if the image with the given key is public or not.
My question:
Can this be done without hitting the database? (some fancy ideas)
Can someone provide a better solution to store and keep track of the pictures?
How would a solution look like where besides public and private pictures also some pictures are shared to firends only?
Please note that this question is not about storing pictures in a database or somewhere else but concerns access rights management of binary resources in a web application environment.
If the DB table is properly indexed and you're using a connection pool, then hitting the DB is cheap. I would just keep it as is. You can at highest have a copy of the table in a Map in the application scope. But this may eat too much server memory. If you're using an ORM framework like JPA/Hibernate, you could also just turn the second level cache on to delegate the caching to the ORM. It will generally do its job very well.
As to the client side caching, you'd like to have a short expire time (1 hour?) and provide a doHead() in the servlet which in turn does basically just the same as doGet() but then without writing any bit to the response body. You would also like to check for If-None-Match and If-Last-Modified headers in the servlet if the client supplied them. You can find here a basic example of a servlet which does that.
My question: Can this be done without
hitting the database? (some fancy
ideas)
Yup, you can do it without hitting the database. We've got something similar and just wanted to put something quick in place.
The user is marking the resource private or public when he's uploading it.
We do something very simple:
public resources have a "tinyurl like" URL, say: abcd.org/aZ3tD (part of the point of the very short tinyurl-link thing is so that people who want to cut/paste/twitter it don't have to use an additional layer of bit.ly or tinyurl)
private resources aren't meant to be shared nor archived, so users don't care about a URL looking like: abcd.org/private/da499c3314e2fdce6a10a8b985489671971c187d
The first part of that URL is the user's ID.
So only the user da499c3314e2 (which must be logged in) can access resource fdce6a10a8b985489671971c187d
You asked for some way to do this without hitting the DB, this should work...
To avoid having to go to the database so often, how about the following URL patterns:
1. http://www.mycompany.com/images/<user_id>/public/<image_key>
2. http://www.mycompany.com/images/<user_id>/private/<image_key>
3. http://www.mycompany.com/images/<user_id>/shared/<image_key>
For 1, obviously no DB lookup is required - the image can be served to anybody immediately. For 2, your servlet would have to check that the ID of the active user matches the user_id in the request - again, hopefully no DB lookup required, just a check of a session variable.
The only case in which a DB call would be needed is 3, to check the relationship between the requesting user and the user who owns the image.
Of course, you'll need to be very careful about caching to ensure that your cache doesn't serve up private or shared images to unauthorised users...
Another alternative can be to store such information in image metadata.
Image metadata API: http://download-llnw.oracle.com/javase/1.4.2/docs/api/javax/imageio/metadata/package-summary.html
You can find related example:
http://download-llnw.oracle.com/javase/1.5.0/docs/guide/imageio/spec/apps.fm5.html
Write dpi metadata to a jpeg image in Java