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})
Comments
Post a Comment