user1406196
user1406196

Reputation: 147

Securing controllers between users with same Role in Spring security

In my application users can manipulate with things, that linked only to them. All users have same role in spring security. So, to forbid user to view not his stuff, I need to implement in some controllers methods my own function to validate users rights.

public void securityValidation(User currentUser, Thing thing)  {
        if(!thing.has(currentUser)) {
            log.warn("Security Control. User: " + user .getId());               
        }
    }

I think It's not cool. It's hard to find in code is the method secured or not. May be Spring has more elegant way for this task?

Or may be I can write my own annotation for securing methods? Do I need annotation processor for that?

Upvotes: 0

Views: 358

Answers (2)

SergeyB
SergeyB

Reputation: 9868

You are referring to Domain Object Security, it is not part of the base security package. Spring Security ACL is what you need, with it you can assert ownership of actual items, for example user 123 can edit item 789. The code below makes sure the current user has admin rights over the entity he is editing:

@PreAuthorize("hasPermission(#entity, 'ADMINISTRATION')")
public SomeEntity update(SomeEntity entity) {
...
}

But keep in mind, you now have to manage those permissions and give/remove them to individual users. There is also a way to do it as part of a group. You can say user 123 and 345 belong to GROUP_SOME_ID and then if you give GROUP_SOME_ID admin permission over an object, users 123 and 345 will get them automatically. Removing user 123 from the group would automatically remove his permission as well.

---- UPDATE ------

Below is sample application context that wires up Spring Security ACL:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
        <property name="permissionEvaluator" ref="permissionEvaluator" />
    </bean>

    <!-- We'll rely on the standard AclPermissionEvaluator  implementation -->
    <bean class="org.springframework.security.acls.AclPermissionEvaluator" id="permissionEvaluator">
        <constructor-arg ref="aclService" />
        <property name="sidRetrievalStrategy" ref="sidRetrievalStrategy" />
        <property name="permissionFactory" ref="permissionFactory"/>
    </bean>

    <bean class="org.springframework.security.acls.domain.SidRetrievalStrategyImpl" id="sidRetrievalStrategy" >
        <constructor-arg ref="roleHierarchy" />
    </bean>

    <!-- Declare an acl service -->
    <bean class="org.springframework.security.acls.jdbc.JdbcMutableAclService" id="aclService">
        <constructor-arg ref="dataSource" />
        <constructor-arg ref="lookupStrategy" />
        <constructor-arg ref="aclCache" />
        <property name="classIdentityQuery" value="select currval(pg_get_serial_sequence('acl_class', 'id'))" />
        <property name="sidIdentityQuery" value="select currval(pg_get_serial_sequence('acl_sid', 'id'))" />
    </bean>

    <!-- Declare a lookup strategy -->
    <bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
        <constructor-arg ref="dataSource" />
        <constructor-arg ref="aclCache" />
        <constructor-arg ref="aclAuthorizationStrategy" />
        <constructor-arg ref="permissionGrantingStrategy" />
        <property name="permissionFactory" ref="permissionFactory"/>
    </bean>

    <bean id="permissionFactory" class="org.springframework.security.acls.domain.DefaultPermissionFactory" />

    <!-- Declare an acl cache -->
    <bean id="aclCache" class="org.springframework.security.acls.domain.SpringCacheBasedAclCache">
        <constructor-arg>
            <bean class="com.example.NoOpCache">
                <constructor-arg value="aclCache" />
            </bean>
        </constructor-arg>
        <constructor-arg ref="permissionGrantingStrategy" />
        <constructor-arg ref="aclAuthorizationStrategy" />
    </bean>

    <!-- Declare an acl authorization strategy -->
    <bean id="aclAuthorizationStrategy" class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
        <constructor-arg>
            <list>
                <bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
                    <constructor-arg value="ROLE_ADMIN" />
                </bean>
                <bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
                    <constructor-arg value="ROLE_ADMIN" />
                </bean>
                <bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
                    <constructor-arg value="ROLE_ADMIN" />
                </bean>
            </list>
        </constructor-arg>
    </bean>

    <bean id="permissionGrantingStrategy" class="org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy" >
        <constructor-arg>
            <bean class="org.springframework.security.acls.domain.ConsoleAuditLogger" />
        </constructor-arg>
    </bean>

    <bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
        <property name="hierarchy">
            <value>
                ROLE_USER > ROLE_ANONYMOUS
                ROLE_SUPER_USER > ROLE_USER
                ROLE_ADMIN > ROLE_SUPER_USER
            </value>
        </property>
    </bean>
</beans>

Upvotes: 1

NimChimpsky
NimChimpsky

Reputation: 47300

@PreAuthorize("hasRole('ROLE_ADMIN')")

above any controller method you want to restrict to admins, for example.

Making sure you define methodSecurityExpressionHandler bean in web context.

Upvotes: 0

Related Questions