We're building a Java web application. We're using EJB containers and JPA with Wildfly 9.2.
Now we want to integrate a permission system in which a user has a certain role, but this role is only granted in combination with a certain entity. I'll name this access resource Department.
So we would have a list of permission for the user stored in such a table:
| User ID | Department | Role |
| ------- | ---------- | ------- |
| 1 | A | MANAGER |
| 1 | B | ADMIN |
| 2 | B | MANAGER |
In addition we have global roles. A user has a set of global roles that will be applied should there not be an entry in the table above with the deparment in question.
| User ID | Role |
| ------- | ------- |
| 1 | VIEWER |
| 3 | MANAGER |
How can we easily check if a user is in a certain role, given a department?
By just using the annotation #RolesAllowed we can check for a certain role, but not restricted to a department.
Remember that enterprise java security roles are about authorization.
So, you could model the department as a role in your security system as well. It's quite OK for a user to be assigned more than one security role.
Therefore, given a manager in department B:
#RolesAllowed({"manager", "B"}
public void someBusinessMethod(...) {
...
}
Only users who are managers and in department B are authorized to invoke this method.
Turns out EJB does not have the features we wanted.
We migrated to Apache Shiro Security and are super happy with it.
Resource based permissions always have to be checked programmatically. Static role and permission based checks can be annotations.
Related
I am developing an app in which the user first login,and if he doesn't have an account he will register after finishing that step he will be directed to a page,there he will add users to his profile like.. his own family members anything like that and when they add a user its going to be saved in a table on an external server(SQL) and then get that in the user list view but how can the user only see his own users and nobody else can see his users except him and so for all other users,like their own data?!
i didn't figure out how to do this yet,any one help me with this task?
any help would be appreciated
It feels like your question is about how to design your database rather than the technical details of how to call the database from you code and display results on your pages?
You need to split your data up into multiple tables. Each table should have a unique id (the id for each row should be different). Then you link rows in tables together by referencing the ids.
One way to achieve what you want would be like this.
A user table:
User
----
Id
Username
Password (hashed)
A family members table:
Family_Members
--------------
User
Member
You put pairs of relationships in the family_members table. So you would put the id of one user in the first column user and the id of one of their family members in the second column member. Then you have a row for every relationship. When you load the table, you find all the rows where user is equal to the user id you are loading.
For example:
User
+--+--------+--------+
|Id|Username|Password|
| 1|Bob |abc |
| 2|Dad |def |
| 3|Mum |ghi |
+--+--------+--------+
And..
Family_members
+----+------+
|User|Member|
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 3 |
| 3 | 1 |
| 3 | 2 |
+----+------+
Then when you load family members for Bob, who's id is 1, you load all the rows from the family_members table that have User==1. Then you go back to the User table and load the details you want for each family member, and get an object like:
User:
- username: Bob
- password: abc
- family:
- User:
- username: Dad
- User:
- username: Mum
Hope this answers your question.
Imagine there are two entities Children and Gifts. Let's say there are 1000 children and 10 gifts. Children will always try to grab available gifts, and gifts will be tagged to children on a "first come, first serve" basis.
Table structure
children table
+----+------+
| id | name |
+----+------+
| 1 | Sam |
| 2 | John |
| 3 | Sara |
+----+------+
gift table
+----+---------+-------------+
| id | gift | children_id |
+----+---------+-------------+
| 1 | Toy Car | 2 |
| 2 | Doll | 3 |
+----+---------+-------------+
Here the children_id is the child who grabbed the gift first.
In my application, I want to update the children_id in such a way that only the first child who initiated the request will get it and rest get a GiftUnavailableException.
How will I ensure that, even if a 1000 requests come at a time to grab a specific gift, only the first one will get it. Or how will I ensure that there are no race conditions for this update.
Are there any spring specific feature that I can make use of or are there any other ways.
I'm using spring-boot as my backend.
I can't post a comment so here I go !
I assume you are using Spring Data JPA.
Then you should use #Transactional annotation : This mean that everytime you are requesting your database, you do a transaction :
Begin Transaction
Execute Transaction
Commit Transaction
Lot of usefull informations about this (Read it !!): Spring #Transactional - isolation, propagation
You will need to seed your Transactional Isolation to Serializable and maybe change the propagation method.
And if you are not using Spring data JPA.. Well There is a synchronized keywords but I think it's a bit awful to use it here.
I have a Play Framework application, which uses Hibernate (5.2.12.Final) to connect to Postgresql (library version: 42.1.4, Postgresql 9.6). I added the following code to my application (I wanted to start using Hibernate Search, so I need session object):
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
session.flush();
The code hangs on the second line and application log is showing:
...
Hibernate: alter table creative_works_inner_tags drop constraint FK1m3t9vv4yl0o36k9nv0bjko87
Hibernate: alter table creative_works_inner_tags drop constraint FKcodcu7qrti27rqnv54bg9o0ma
Hibernate: alter table entry_headings drop constraint FK4tx66i2tsu651p4s176ea2nvk
So it looks like Hibernate hangs somewhere in the middle of schema update, which is triggered by session start. I also see a lock in Postresql:
select pid,
usename,
pg_blocking_pids(pid) as blocked_by,
query as blocked_query
from pg_stat_activity
where cardinality(pg_blocking_pids(pid)) > 0;
pid | usename | blocked_by | blocked_query
-----+---------+------------+------------------------------------------------------------------------
18804| pbl | {18499} | alter table entry_headings drop constraint FK4tx66i2tsu651p4s176ea2nvk
I don't know what to do about it. It also happens with previous library versions.
Update
The pid that blocks the ALTER TABLE command comes from the same application:
datid | datname | pid | usesysid | usename | application_name | client_addr | client_hostname | client_port | backend_start | xact_start | query_start | state_change | wait_event_type | wait_event | state | backend_xid | backend_xmin | query
-------+---------+-------+----------+---------+------------------------+-------------+-----------------+-------------+------------------------------+-------------------------------+-------------------------------+-------------------------------+-----------------+------------+---------------------+-------------+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
16388 | pbl | 18499 | 16387 | pbl | PostgreSQL JDBC Driver | 127.0.0.1 | | 51192 | 2018-01-12 10:23:11.62866+01 | 2018-01-12 10:24:11.363172+01 | 2018-01-12 10:24:11.574648+01 | 2018-01-12 10:24:11.574693+01 | | | idle in transaction | | 373556 | select children0_.parent_code as parent_c3_179_0_, children0_.code as code1_179_0_, children0_.code as code1_179_1_, children0_.ord as ord2_179_1_, children0_.parent_code as parent_c3_179_1_ from record_types children0_ where children0_.parent_code=$1
I don't trigger this SELECT explicitly in my code. It must be another Hibernate operation which happens automatically. Also, this code fragment is not explicitly parallel.
Thank you very much for the comments. They helped me to solve the problem.
The problem was: I was using both hibernate.cfg.xml (with session obtained from SessionFactory) and persistance.xml (with another session obtained from EntityManager). This was a result of integrating two applications into one and I think it caused wo Hibernate sessions to be created. I integrated necessary configuration from hibernate.cfg.xml into persistence.xml (had to change format) and it helped.
I have 3 controllers annotated with #PreAuthorize("hasAnyAuthority(x)") where x is
'ROLE_ADMIN'
'ROLE_ADMIN','ROLE_MID'
'ROLE_ADMIN','ROLE_MID','ROLE_LOW'
Crucial point: If a user has ONE authority, these annotations work just fine. Ex: A user with only ROLE_ADMIN can access all methods on all 3.
BUT if a user has some other role as well, e.g. ROLE_ADMIN,ROLE_OTHER, then all I get "Access Denied" on across all three controllers.
See this table for what I'm talking about. (hAA=hasAnyAuthority):
+-----------------------+-------------------+------------------------------+-----------------------------------------+
| Authorities | hAA('ROLE_ADMIN') | hAA('ROLE_ADMIN','ROLE_MID') | hAA('ROLE_ADMIN','ROLE_MID','ROLE_LOW') |
+-----------------------+-------------------+------------------------------+-----------------------------------------+
| ROLE_ADMIN | YES | YES | YES |
| ROLE_MID | NO | YES | YES |
| ROLE_LOW | NO | NO | YES |
| ROLE_ADMIN,ROLE_OTHER | NO | NO | NO |
| ROLE_MID,ROLE_OTHER | NO | NO | NO |
| ROLE_LOW,ROLE_OTHER | NO | NO | NO |
+-----------------------+-------------------+------------------------------+-----------------------------------------+
Just to drive the point home, I have a user whose getAuthorites returns (as string) "[ROLE_MID,mid.mid12345]" and all three controllers fail for that user. Shouldn't "hasAnyAuthority('ROLE_MID')" work for him? Why would having "mid.mid12345" cause it to fail?
PS I've tried hasAnyRole as well with the same results.
I figure out that in older versions of Spring Security 4, whole comma-separated list is acceptable without using single-quote for each authority
Example:
hasAnyAuthority('AUTHORITY1,AUTHORITY2,AUTHORTIY3')
In Spring Security 5, this is not an acceptable list so it should be replaced with
hasAnyAuthority('AUTHORITY1', 'AUTHORITY2', 'AUTHORTIY3')
Took some time to figure out so I would like to share here
I am not sure but try without single quotes and just comma-separated, take a look to documentation(https://docs.spring.io/spring-security/site/docs/current/reference/html/el-access.html)
hasAnyAuthority([authority1,authority2]) Returns true if the current principal has any of the supplied roles (given as a comma-separated list of strings)
Also I think your roles cannot start with ROLE_.
Returns true if the current principal has any of the supplied roles (given as a comma-separated list of strings). By default if the supplied role does not start with 'ROLE_' it will be added. This can be customized by modifying the defaultRolePrefix on DefaultWebSecurityExpressionHandler.
I figured out the issue. I have a UserDetailsService set up with the sole loadUserByUsername method overridden in order to connect my database entity user, Customuser, to Spring Security's Userdetails.User.
But my conversion from one to the other was incorrect.
INCORRECT
User user = new User(customuser.getUsername(), customuser.getPassword(), AuthorityUtils.createAuthorityList(customuser.getAuthorityString()));
CORRECT
User user = new User(customuser.getUsername(), customuser.getPassword(), customuser.getAuthoritiesList()); // see below
My Customuser object stores a comma-separated list of the authorities the user has. When using AuthorityUtils.createAuthorityList, it was taking that string, whether it was "ROLE_ADMIN" or "ROLE_ADMIN,ROLE_OTHER" and making the entire string ONE authority. The latter of the two above would have been a single authority authority of "ROLE_ADMIN,ROLE_OTHER". (This explains why users with only one authority were working just fine and any user with mutiple was failing.)
I had to create a custom method within Customuser to chop that custom CSV string into individual authorities before creating my UserDetails.User object in loadUserByUsername.
public Collection<? extends GrantedAuthority> getAuthoritiesList()
{
StringTokenizer st = new StringTokenizer(authorityString,",");
List<SimpleGrantedAuthority> returnlist = new ArrayList<SimpleGrantedAuthority>();
while(st.hasMoreTokens())
{
returnlist.add(new SimpleGrantedAuthority(st.nextToken()));
}
return returnlist;
}
Hope this helps someone else!
I need to copy data from one data table to another as mentioned below
When I enter company manager details of:
|NAME |VALUE |
|title |$randomList |
|firstName |$random |
|initial |$random |
|surname |$random |
When I enter company employee details of
|NAME |VALUE |
|title |$randomList |
|firstName | |
|initial | |
|surname | |
I am new to jbehave. In the above tables when i execute this scenario random characters will be generated and assigned to firstname,initial,surname in the 1st table I somehow need the same data when I execute the second table. I know we should parametrize by using examples table but in this case I don't want to use it. so how to copy the data from one table to another.