Cloud Native 9 min read

Implementing Distributed Authentication in Spring Cloud Alibaba Using Custom Annotations

This article demonstrates how to move authentication from the gateway to downstream microservices in a Spring Cloud Alibaba setup by disabling the gateway’s ReactiveAuthorizationManager, defining three custom security annotations, creating an AOP aspect to enforce them, and showing practical usage examples with role‑based access control and Feign calls.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Implementing Distributed Authentication in Spring Cloud Alibaba Using Custom Annotations

In this article the author explains how to shift authentication responsibilities from the gateway to downstream microservices in a Spring Cloud Alibaba environment.

First, the gateway’s ReactiveAuthorizationManager is disabled by permitting all requests, as shown in the provided route configuration code:

http<br/> ....<br/> //白名单直接放行<br/>  .pathMatchers(ArrayUtil.toArray(whiteUrls.getUrls(), String.class)).permitAll()<br/> //其他的任何请求直接放行<br/>  .anyExchange().permitAll()<br/>  .....<br/>

Then three custom annotations— @RequiresLogin, @RequiresPermissions, and @RequiresRoles —are defined to express login, permission, and role requirements respectively. Their source code is shown below:

/**
 * @author 公众号:码猿技术专栏
 * @url: www.java-family.cn
 * @description 登录认证的注解,标注在controller方法上,一定要是登录才能的访问的接口
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface RequiresLogin {}
/**
 * @author 公众号:码猿技术专栏
 * @url: www.java-family.cn
 * @description 标注在controller方法上,确保拥有指定权限才能访问该接口
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface RequiresPermissions {
    String[] value default {};
    Logical logical() default Logical.AND;
}
/**
 * @author 公众号:码猿技术专栏
 * @url: www.java-family.cn
 * @description 标注在controller方法上,确保拥有指定的角色才能访问该接口
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface RequiresRoles {
    String[] value default {OAuthConstant.ROLE_ROOT_CODE, OAuthConstant.ROLE_ADMIN_CODE};
    Logical logical() default Logical.AND;
}

Next, an AOP aspect ( PreAuthorizeAspect) intercepts methods annotated with these annotations, checks the current token for login status, roles, and permissions, and throws appropriate exceptions when validation fails. Key parts of the aspect are:

@Aspect
@Component
public class PreAuthorizeAspect {
    public static final String POINTCUT_SIGN = " @annotation(com.mugu.blog.common.annotation.RequiresLogin) || "
            + "@annotation(com.mugu.blog.common.annotation.RequiresPermissions) || "
            + "@annotation(com.mugu.blog.common.annotation.RequiresRoles)";

    @Pointcut(POINTCUT_SIGN)
    public void pointcut() {}

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        checkMethodAnnotation(signature.getMethod());
        try {
            Object obj = joinPoint.proceed();
            return obj;
        } catch (Throwable e) {
            throw e;
        }
    }

    public void checkMethodAnnotation(Method method) {
        RequiresLogin requiresLogin = method.getAnnotation(RequiresLogin.class);
        if (requiresLogin != null) { doCheckLogin(); }
        RequiresRoles requiresRoles = method.getAnnotation(RequiresRoles.class);
        if (requiresRoles != null) { doCheckRole(requiresRoles); }
        RequiresPermissions requiresPermissions = method.getAnnotation(RequiresPermissions.class);
        if (requiresPermissions != null) { doCheckPermissions(requiresPermissions); }
    }
    // ... implementations of doCheckLogin, doCheckRole, doCheckPermissions omitted for brevity
}

Finally, usage examples demonstrate applying @RequiresRoles to controller methods for role‑based access control, and discuss the impact on Feign client calls. For instance, an endpoint that adds an article is protected as follows:

@RequiresRoles
@AvoidRepeatableCommit
@ApiOperation("添加文章")
@PostMapping("/add")
public ResultMsg<Void> add(@RequestBody @Valid ArticleAddReq req) {
    // ...
}

The article concludes that while delegating authentication to downstream services can solve certain scenarios, centralizing authentication at the gateway is generally recommended unless specific business needs dictate otherwise.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaaopAuthenticationannotationsSpring Cloud
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.