You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Spring-Security注解生成Swagger接口授权信息并复用注解?

Awesome question! Dealing with duplicate authorization config between Spring Security and Swagger is a common pain point—let's fix this properly. The solution below addresses both your questions: auto-generating per-endpoint Swagger authorization info and reusing your existing Spring Security annotations to avoid redundant work.

Solution: Auto-Generate Swagger Authorization from Spring Security Annotations

Instead of manually duplicating role info in both Spring Security and Swagger annotations, we'll build a custom Springfox plugin that automatically reads authorization rules from @Secured, @PreAuthorize, or @RolesAllowed annotations and injects them into your Swagger documentation.

Step 1: Create a Custom Springfox Plugin

This plugin hooks into Springfox's operation-building pipeline to extract authorization data from your Spring Security annotations:

import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
import springfox.documentation.builders.AuthorizationScopeBuilder;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.OperationBuilderPlugin;
import springfox.documentation.spi.service.contexts.OperationContext;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.SecurityReference;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class SpringSecuritySwaggerPlugin implements OperationBuilderPlugin {

    @Override
    public void apply(OperationContext context) {
        List<String> authorizedRoles = new ArrayList<>();

        // Extract roles from @Secured annotation
        Optional<Secured> securedAnnotation = context.findAnnotation(Secured.class);
        securedAnnotation.ifPresent(secured -> authorizedRoles.addAll(Arrays.asList(secured.value())));

        // Extract roles/permissions from @PreAuthorize expression
        Optional<PreAuthorize> preAuthAnnotation = context.findAnnotation(PreAuthorize.class);
        preAuthAnnotation.ifPresent(preAuth -> {
            // Parse common cases like hasRole('ROLE_ADMIN') or hasAnyRole('ROLE_USER','ROLE_EDITOR')
            String expression = preAuth.value();
            List<String> parsedRoles = Arrays.stream(expression.split("'"))
                    .filter(s -> s.startsWith("ROLE_") || s.startsWith("PERMISSION_"))
                    .collect(Collectors.toList());
            authorizedRoles.addAll(parsedRoles);
        });

        // Attach authorization info to Swagger operation if roles exist
        if (!authorizedRoles.isEmpty()) {
            List<AuthorizationScope> scopes = authorizedRoles.stream()
                    .map(role -> new AuthorizationScopeBuilder()
                            .scope(role)
                            .description("Required role/permission: " + role)
                            .build())
                    .collect(Collectors.toList());

            SecurityReference securityRef = SecurityReference.builder()
                    .reference("BearerAuth") // Match your Swagger security scheme name
                    .scopes(scopes.toArray(new AuthorizationScope[0]))
                    .build();

            context.operationBuilder().security(List.of(securityRef));
        }
    }

    @Override
    public boolean supports(DocumentationType documentationType) {
        return true;
    }
}

Step 2: Register the Plugin in Your Swagger Config

Update your SwaggerConfig to register the plugin and configure your security scheme (e.g., Bearer token authentication):

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.SecurityScheme;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.List;

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.your.app.package"))
                .paths(PathSelectors.any())
                .build()
                .securitySchemes(List.of(apiKey()))
                .securityContexts(List.of(securityContext()))
                .plugins(new SpringSecuritySwaggerPlugin()); // Register our custom plugin
    }

    // Define your security scheme (e.g., Bearer token)
    private SecurityScheme apiKey() {
        return new ApiKey("BearerAuth", "Authorization", "header");
    }

    private SecurityContext securityContext() {
        return SecurityContext.builder()
                .securityReferences(defaultAuth())
                .forPaths(PathSelectors.any())
                .build();
    }

    private List<SecurityReference> defaultAuth() {
        // Leave empty—our plugin will add per-endpoint security refs dynamically
        return List.of();
    }
}

Step 3: Use Spring Security Annotations Normally

Now you can annotate your controllers with Spring Security annotations as usual—Swagger will automatically pick up the authorization rules:

@RestController
@RequestMapping("/api/models")
public class ModelController {

    @GetMapping
    @Secured("ROLE_USER")
    public List<Model> getAllModels() {
        // Your logic here
    }

    @PostMapping
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasAuthority('PERMISSION_CREATE_MODEL')")
    public Model createModel(@RequestBody Model model) {
        // Your logic here
    }
}

How This Solves Your Problems

  1. Per-endpoint authorization info: Each API's Swagger entry will show the exact roles/permissions required, pulled directly from your Spring Security annotations.
  2. No duplicate maintenance: You only need to update your Spring Security annotations—Swagger stays in sync automatically, eliminating the risk of mismatched configs.

Notes for Complex Expressions

If you use advanced @PreAuthorize expressions (e.g., hasAuthority('EDIT') and authentication.name == #model.owner), you can extend the parsing logic in the plugin. For example, add regex patterns to extract custom permissions, or integrate a SpEL parser for full expression evaluation.


内容的提问来源于stack exchange,提问作者Mahatma_Fatal_Error

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:52:27