How to block certain URLs access for some user type in Hybris?

Scenario:

How to block certain URLs access for some user type in Hybris?

Solution:

In general, we should maintain spring Authorities/group for such users so that it can be blocked from spring-security. But in my case, I don't have that choice. There are already many userType which can be identified when the user logged in and stored it in session. Here I have to use same. So I have decided to use Spring AOP to serve my aspect around the point-cut(custom annotation). In this post, I am not going to cover AOP in detail. If you don't know anything about Spring AOP. You should first explore it first.

1. Create Annotation AllowUsers and BlockUsers
package com.hybris.storefront.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Retention(RetentionPolicy.RUNTIME)
@Target(
{ ElementType.METHOD })
public @interface AllowUsers
{
    String[] roles();
}
Like the way, you can create BlockUsers annotation. We want this annotation on method level so you can see @Target as ElementType.METHOD.

2. Create Aspect
package com.hybris.storefront.handler;

import javax.annotation.Resource;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import com.hybris.extended.service.HybrisB2BUnitService;
import com.hybris.extended.util.StaticStringUtils;
import com.hybris.storefront.annotations.AllowUsers;
import com.hybris.storefront.annotations.BlockUsers;

public class UsersRoleValidationHandler
{

    public static final String REDIRECT_TO_HOME = "redirect:/";

    @Resource
    private HybrisB2BUnitService hybrisB2BUnitService;

    public Object validateUserAccess(final ProceedingJoinPoint pjp) throws Throwable
    {
        final MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        final AllowUsers allowUsersAnnotation = methodSignature.getMethod().getAnnotation(AllowUsers.class);
        if (allowUsersAnnotation != null)
        {
            String[] roles = allowUsersAnnotation.roles();
            if (roles != null && roles.length > 0 && !isUserMatchWithRole(roles))
            {
                return REDIRECT_TO_HOME;
            }
        }

        final BlockUsers blockUsersAnnotation = methodSignature.getMethod().getAnnotation(BlockUsers.class);
        if (blockUsersAnnotation != null)
        {
            String[] roles = blockUsersAnnotation.roles();
            if (roles != null && roles.length > 0 && isUserMatchWithRole(roles))
            {
                return REDIRECT_TO_HOME;
            }
        }

        return pjp.proceed();
    }

    private boolean isUserMatchWithRole(String[] roles)
    {
        for (String role : roles)
        {
            switch (role)
            {
                case StaticStringUtils.TYPE1_CUSTOMER:
                    if (hybrisB2BUnitService.isType1Customer())
                    {
                        return true;
                    }
                    break;
                case StaticStringUtils.TYPE2_CUSTOMER:
                    if (hybrisB2BUnitService.isType2Customer())
                    {
                        return true;
                    }
            }
        }
        return false;
    }
}
This class is an aspect, in which we first fetch define roles from annotation and cross check with the current user role. If match we will allow the method to proceed pjp.proceed() otherwise redirect to home.

3. configure AOP and bean in spring-mvc-config.xml
<alias name="defaultUsersRoleValidationHandler" alias="usersRoleValidationHandler" />
<bean id='defaultUsersRoleValidationHandler' class="com.hybris.storefront.handler.UsersRoleValidationHandler" />


<aop:config proxy-target-class="true">
    <aop:pointcut id="usersRoleValidationPoint"  expression="@annotation(com.hybris.storefront.annotations.AllowUsers) || @annotation(com.hybris.storefront.annotations.BlockUsers)" />
    <aop:aspect ref="defaultUsersRoleValidationHandler">
        <aop:around pointcut-ref="usersRoleValidationPoint" method="validateUserAccess" />
    </aop:aspect>
</aop:config>
Here point-cut match if calling method has AllowUser or BlockUsers annotation. If match, our bean/aspect method will be triggered.

4. Add Annotation at request matching method.
@AllowUsers(roles = { StaticStringUtils.TYPE1_CUSTOMER, StaticStringUtils.TYPE1_CUSTOMER})

@BlockUsers(roles = { StaticStringUtils.TYPE2_CUSTOMER, StaticStringUtils.TYPE3_CUSTOMER})
Author Image

Ankitkumar Patel

Sr. SAP Hybris consultant, having 15+ years experience in SAP Commerce Cloud (Hybris), SAP Spartacus. Extensive experience in SAP Hybris development, third-party integrations, project architecture and design... Read more

Comments

Popular posts from this blog

Hybris flexible search query examples

How to remove or update all data records in Hybris?

How to Install temporary Hybris license?